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:
authorAlexander Pinzon Fernandez <apinzonf@gmail.com>2013-12-11 20:10:22 +0400
committerAlexander Pinzon Fernandez <apinzonf@gmail.com>2013-12-11 20:10:22 +0400
commit2658a3c1b44717f497f187a38000c804eb37bbba (patch)
treeee55c673feabced8b6ec8bf9a8aa4d82a3cda3db
parent4005cb1c6a63a217df0e887c741beee2c1359301 (diff)
parent09b859d03f0ee138c4273ef8460e91d9888387a1 (diff)
Merge branch 'master' into soc-2013-sketch_meshsoc-2013-sketch_mesh
Conflicts: release/scripts/addons source/blender/blenloader/intern/readfile.c source/blender/blenloader/intern/writefile.c source/blender/editors/object/object_modifier.c source/blender/makesrna/intern/rna_modifier.c source/blender/modifiers/intern/MOD_laplaciandeform.c
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt26
-rw-r--r--SConstruct27
-rwxr-xr-xbuild_files/build_environment/install_deps.sh394
-rw-r--r--build_files/buildbot/master.cfg5
-rw-r--r--build_files/cmake/Modules/FindOpenEXR.cmake28
-rw-r--r--build_files/cmake/buildinfo.cmake23
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/macros.cmake4
-rw-r--r--build_files/cmake/packaging.cmake24
-rw-r--r--build_files/scons/config/Modules/FindPython.py2
-rw-r--r--build_files/scons/config/linux-config.py2
-rw-r--r--build_files/scons/tools/Blender.py16
-rw-r--r--build_files/scons/tools/btools.py3
-rw-r--r--doc/python_api/examples/bpy.types.UIList.1.py9
-rw-r--r--doc/python_api/examples/bpy.types.UIList.2.py4
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst10
-rw-r--r--doc/python_api/rst/include__bmesh.rst1
-rw-r--r--doc/python_api/sphinx_doc_gen.py6
-rwxr-xr-xdoc/python_api/sphinx_doc_gen.sh10
-rwxr-xr-xextern/carve/bundle.sh2
-rw-r--r--extern/carve/files.txt2
-rw-r--r--extern/carve/include/carve/aabb.hpp6
-rw-r--r--extern/carve/include/carve/aabb_impl.hpp17
-rw-r--r--extern/carve/include/carve/csg.hpp16
-rw-r--r--extern/carve/include/carve/debug_hooks.hpp4
-rw-r--r--extern/carve/include/carve/face_impl.hpp4
-rw-r--r--extern/carve/include/carve/geom.hpp4
-rw-r--r--extern/carve/include/carve/geom2d.hpp4
-rw-r--r--extern/carve/include/carve/geom3d.hpp77
-rw-r--r--extern/carve/include/carve/geom_impl.hpp47
-rw-r--r--extern/carve/include/carve/interpolator.hpp309
-rw-r--r--extern/carve/include/carve/mesh.hpp1
-rw-r--r--extern/carve/include/carve/mesh_impl.hpp93
-rw-r--r--extern/carve/include/carve/polyhedron_impl.hpp33
-rw-r--r--extern/carve/include/carve/polyline_decl.hpp4
-rw-r--r--extern/carve/include/carve/polyline_impl.hpp6
-rw-r--r--extern/carve/include/carve/rtree.hpp12
-rwxr-xr-xextern/carve/include/carve/win32.h2
-rw-r--r--extern/carve/lib/geom2d.cpp8
-rw-r--r--extern/carve/lib/intersect.cpp11
-rw-r--r--extern/carve/lib/intersect_face_division.cpp30
-rw-r--r--extern/carve/lib/triangulator.cpp7
-rwxr-xr-xextern/carve/mkfiles.sh2
-rw-r--r--extern/carve/patches/clang_is_heap_fix.patch17
-rw-r--r--extern/carve/patches/files/random.hpp773
-rw-r--r--extern/carve/patches/series1
-rw-r--r--extern/libmv/libmv/numeric/numeric.h2
-rw-r--r--extern/libmv/third_party/ceres/CMakeLists.txt89
-rw-r--r--extern/libmv/third_party/ceres/ChangeLog914
-rw-r--r--extern/libmv/third_party/ceres/SConscript35
-rwxr-xr-xextern/libmv/third_party/ceres/bundle.sh105
-rw-r--r--extern/libmv/third_party/ceres/files.txt27
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h46
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/ceres.h6
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h33
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/dynamic_numeric_diff_cost_function.h265
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h2
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h4
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/macros.h5
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h30
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/iteration_callback.h4
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/jet.h194
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h42
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h7
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/ordered_groups.h7
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/problem.h22
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/rotation.h73
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/solver.h135
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/types.h65
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc120
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h96
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc10
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc18
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/collections_port.h60
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc65
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/corrector.cc29
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc80
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc28
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc25
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc24
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generate_partitioned_matrix_view_specializations.py226
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_d_d_d.cc53
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc56
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc22
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc21
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc38
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/lapack.cc76
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/lapack.h34
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search.cc266
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc49
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc102
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.h24
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc48
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/minimizer.h3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc376
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h87
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view_impl.h380
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial.cc101
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial.h1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/preconditioner.h3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem.cc21
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc61
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc217
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h87
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc142
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h15
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc24
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc107
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h71
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver.cc23
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc147
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.h27
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc73
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc136
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.h39
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc170
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/types.cc31
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc99
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h3
-rw-r--r--extern/libmv/third_party/glog/src/logging.cc1
-rw-r--r--intern/CMakeLists.txt5
-rw-r--r--intern/audaspace/intern/AUD_JOSResampleReader.cpp2
-rw-r--r--intern/cycles/CMakeLists.txt12
-rw-r--r--intern/cycles/SConscript10
-rw-r--r--intern/cycles/app/CMakeLists.txt6
-rw-r--r--intern/cycles/app/cycles_server.cpp6
-rw-r--r--intern/cycles/app/cycles_xml.cpp28
-rw-r--r--intern/cycles/blender/CCL_api.h2
-rw-r--r--intern/cycles/blender/addon/engine.py4
-rw-r--r--intern/cycles/blender/addon/properties.py11
-rw-r--r--intern/cycles/blender/addon/ui.py30
-rw-r--r--intern/cycles/blender/blender_curves.cpp12
-rw-r--r--intern/cycles/blender/blender_mesh.cpp24
-rw-r--r--intern/cycles/blender/blender_object.cpp56
-rw-r--r--intern/cycles/blender/blender_python.cpp40
-rw-r--r--intern/cycles/blender/blender_session.cpp30
-rw-r--r--intern/cycles/device/CMakeLists.txt6
-rw-r--r--intern/cycles/device/device.cpp5
-rw-r--r--intern/cycles/device/device.h2
-rw-r--r--intern/cycles/device/device_cpu.cpp58
-rw-r--r--intern/cycles/device/device_cuda.cpp3
-rw-r--r--intern/cycles/device/device_intern.h2
-rw-r--r--intern/cycles/device/device_multi.cpp9
-rw-r--r--intern/cycles/device/device_network.cpp457
-rw-r--r--intern/cycles/device/device_network.h53
-rw-r--r--intern/cycles/device/device_opencl.cpp3
-rw-r--r--intern/cycles/kernel/CMakeLists.txt9
-rw-r--r--intern/cycles/kernel/closure/volume.h5
-rw-r--r--intern/cycles/kernel/kernel.h9
-rw-r--r--intern/cycles/kernel/kernel_primitive.h19
-rw-r--r--intern/cycles/kernel/kernel_shader.h5
-rw-r--r--intern/cycles/kernel/kernel_sse41.cpp76
-rw-r--r--intern/cycles/kernel/kernel_types.h2
-rw-r--r--intern/cycles/kernel/osl/background.cpp33
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp17
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp17
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp15
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp32
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.h8
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp25
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h56
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp51
-rw-r--r--intern/cycles/kernel/osl/osl_services.h7
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp65
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h5
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h16
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h12
-rw-r--r--intern/cycles/render/attribute.cpp10
-rw-r--r--intern/cycles/render/nodes.cpp36
-rw-r--r--intern/cycles/render/nodes.h2
-rw-r--r--intern/cycles/render/osl.cpp36
-rw-r--r--intern/cycles/render/osl.h4
-rw-r--r--intern/cycles/render/session.cpp18
-rw-r--r--intern/cycles/subd/CMakeLists.txt9
-rw-r--r--intern/cycles/subd/subd_build.cpp669
-rw-r--r--intern/cycles/subd/subd_build.h73
-rw-r--r--intern/cycles/subd/subd_dice.cpp100
-rw-r--r--intern/cycles/subd/subd_dice.h42
-rw-r--r--intern/cycles/subd/subd_edge.h70
-rw-r--r--intern/cycles/subd/subd_face.h109
-rw-r--r--intern/cycles/subd/subd_mesh.cpp493
-rw-r--r--intern/cycles/subd/subd_mesh.h40
-rw-r--r--intern/cycles/subd/subd_patch.cpp163
-rw-r--r--intern/cycles/subd/subd_patch.h40
-rw-r--r--intern/cycles/subd/subd_ring.cpp236
-rw-r--r--intern/cycles/subd/subd_ring.h75
-rw-r--r--intern/cycles/subd/subd_split.cpp31
-rw-r--r--intern/cycles/subd/subd_split.h11
-rw-r--r--intern/cycles/subd/subd_stencil.cpp101
-rw-r--r--intern/cycles/subd/subd_stencil.h65
-rw-r--r--intern/cycles/subd/subd_vert.h121
-rw-r--r--intern/cycles/util/util_math.h13
-rw-r--r--intern/cycles/util/util_string.cpp19
-rw-r--r--intern/cycles/util/util_string.h2
-rw-r--r--intern/cycles/util/util_system.cpp9
-rw-r--r--intern/cycles/util/util_system.h1
-rw-r--r--intern/cycles/util/util_types.h28
-rw-r--r--intern/elbeem/intern/ntl_blenderdumper.cpp2
-rw-r--r--intern/elbeem/intern/particletracer.cpp2
-rw-r--r--intern/guardedalloc/intern/mmap_win.c14
-rw-r--r--intern/itasc/Armature.cpp2
-rw-r--r--intern/itasc/kdl/tree.cpp2
-rw-r--r--intern/itasc/kdl/tree.hpp24
-rw-r--r--intern/itasc/kdl/treefksolverpos_recursive.cpp17
-rw-r--r--intern/itasc/kdl/treefksolverpos_recursive.hpp2
-rw-r--r--intern/itasc/kdl/treejnttojacsolver.cpp6
-rw-r--r--intern/locale/SConscript4
-rw-r--r--intern/memutil/MEM_CacheLimiter.h105
-rw-r--r--intern/opencolorio/fallback_impl.cc10
-rw-r--r--intern/opencolorio/ocio_capi.cc10
-rw-r--r--intern/opencolorio/ocio_capi.h3
-rw-r--r--intern/opencolorio/ocio_impl.cc10
-rw-r--r--intern/opencolorio/ocio_impl.h9
-rw-r--r--release/scripts/freestyle/data/env_map/brown00.pngbin22195 -> 0 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray00.pngbin18513 -> 0 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray01.pngbin9915 -> 0 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray02.pngbin7197 -> 0 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray03.pngbin16109 -> 0 bytes
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py2
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py1
-rw-r--r--release/scripts/modules/sys_info.py30
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml14
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml14
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml14
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml14
-rw-r--r--release/scripts/presets/interface_theme/ubuntu_ambiance.xml14
-rw-r--r--release/scripts/startup/bl_operators/node.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py72
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py18
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py5
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py15
-rw-r--r--release/scripts/startup/bl_ui/space_image.py6
-rw-r--r--release/scripts/startup/bl_ui/space_info.py3
-rw-r--r--release/scripts/startup/bl_ui/space_node.py3
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py32
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py19
-rw-r--r--release/scripts/startup/nodeitems_builtins.py3
-rw-r--r--release/scripts/templates_osl/gabor_noise.osl17
-rw-r--r--release/scripts/templates_osl/noise.osl21
-rw-r--r--release/scripts/templates_osl/temperature_to_rgb.osl9
-rw-r--r--release/scripts/templates_osl/wavelength_to_rgb.osl9
-rw-r--r--release/scripts/templates_osl/wireframe.osl11
-rw-r--r--release/scripts/templates_py/ui_list_simple.py9
-rw-r--r--source/blender/blenfont/BLF_api.h14
-rw-r--r--source/blender/blenfont/intern/blf.c32
-rw-r--r--source/blender/blenfont/intern/blf_dir.c8
-rw-r--r--source/blender/blenfont/intern/blf_font.c16
-rw-r--r--source/blender/blenfont/intern/blf_internal.h8
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h4
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h4
-rw-r--r--source/blender/blenkernel/BKE_lattice.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h9
-rw-r--r--source/blender/blenkernel/BKE_screen.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c8
-rw-r--r--source/blender/blenkernel/intern/armature.c12
-rw-r--r--source/blender/blenkernel/intern/blender.c13
-rw-r--r--source/blender/blenkernel/intern/bmfont.c9
-rw-r--r--source/blender/blenkernel/intern/brush.c15
-rw-r--r--source/blender/blenkernel/intern/camera.c9
-rw-r--r--source/blender/blenkernel/intern/curve.c72
-rw-r--r--source/blender/blenkernel/intern/customdata.c18
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c3
-rw-r--r--source/blender/blenkernel/intern/displist.c52
-rw-r--r--source/blender/blenkernel/intern/fcurve.c4
-rw-r--r--source/blender/blenkernel/intern/freestyle.c1
-rw-r--r--source/blender/blenkernel/intern/gpencil.c20
-rw-r--r--source/blender/blenkernel/intern/image.c45
-rw-r--r--source/blender/blenkernel/intern/implicit.c6
-rw-r--r--source/blender/blenkernel/intern/lamp.c3
-rw-r--r--source/blender/blenkernel/intern/lattice.c58
-rw-r--r--source/blender/blenkernel/intern/mball.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.c7
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c93
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c12
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/node.c40
-rw-r--r--source/blender/blenkernel/intern/object.c25
-rw-r--r--source/blender/blenkernel/intern/particle.c5
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/sca.c5
-rw-r--r--source/blender/blenkernel/intern/scene.c5
-rw-r--r--source/blender/blenkernel/intern/screen.c33
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c4
-rw-r--r--source/blender/blenkernel/intern/smoke.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c307
-rw-r--r--source/blender/blenkernel/intern/text.c34
-rw-r--r--source/blender/blenkernel/intern/tracking.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c13
-rw-r--r--source/blender/blenkernel/intern/writeavi.c13
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c31
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h11
-rw-r--r--source/blender/blenlib/BLI_math_base.h31
-rw-r--r--source/blender/blenlib/BLI_math_color.h19
-rw-r--r--source/blender/blenlib/BLI_math_geom.h10
-rw-r--r--source/blender/blenlib/BLI_math_vector.h4
-rw-r--r--source/blender/blenlib/BLI_memarena.h7
-rw-r--r--source/blender/blenlib/BLI_path_util.h5
-rw-r--r--source/blender/blenlib/BLI_polyfill2d.h44
-rw-r--r--source/blender/blenlib/BLI_rect.h4
-rw-r--r--source/blender/blenlib/BLI_utildefines.h65
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c2
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c50
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c4
-rw-r--r--source/blender/blenlib/intern/math_base.c4
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c7
-rw-r--r--source/blender/blenlib/intern/math_color.c197
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c50
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c12
-rw-r--r--source/blender/blenlib/intern/math_geom.c117
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c19
-rw-r--r--source/blender/blenlib/intern/math_interp.c61
-rw-r--r--source/blender/blenlib/intern/math_matrix.c40
-rw-r--r--source/blender/blenlib/intern/math_rotation.c74
-rw-r--r--source/blender/blenlib/intern/math_vector.c8
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c19
-rw-r--r--source/blender/blenlib/intern/path_util.c35
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c452
-rw-r--r--source/blender/blenlib/intern/rct.c59
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/intern/readfile.c2502
-rw-r--r--source/blender/blenloader/intern/readfile.h6
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2648
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c1
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/bmesh/CMakeLists.txt8
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c7
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c284
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c9
-rw-r--r--source/blender/bmesh/operators/bmo_beautify.c3
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c6
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c9
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c6
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c90
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c16
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c60
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c595
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c3
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c8
-rw-r--r--source/blender/collada/DocumentImporter.cpp4
-rw-r--r--source/blender/collada/GeometryExporter.cpp18
-rw-r--r--source/blender/collada/GeometryExporter.h2
-rw-r--r--source/blender/collada/LightExporter.cpp5
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp191
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h2
-rw-r--r--source/blender/compositor/intern/COM_Node.h1
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h12
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_DefocusNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_BoxMaskOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.cpp124
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.h7
-rw-r--r--source/blender/compositor/operations/COM_EllipseMaskOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cpp14
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cpp116
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp42
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp101
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp14
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c334
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c3
-rw-r--r--source/blender/editors/animation/anim_markers.c20
-rw-r--r--source/blender/editors/animation/keyframes_general.c8
-rw-r--r--source/blender/editors/animation/keyframing.c14
-rw-r--r--source/blender/editors/armature/CMakeLists.txt8
-rw-r--r--source/blender/editors/armature/armature_add.c6
-rw-r--r--source/blender/editors/armature/armature_edit.c17
-rw-r--r--source/blender/editors/armature/armature_intern.h1
-rw-r--r--source/blender/editors/armature/armature_naming.c33
-rw-r--r--source/blender/editors/armature/armature_ops.c3
-rw-r--r--source/blender/editors/armature/armature_relations.c5
-rw-r--r--source/blender/editors/armature/armature_select.c122
-rw-r--r--source/blender/editors/armature/armature_skinning.c6
-rw-r--r--source/blender/editors/armature/armature_utils.c43
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c10
-rw-r--r--source/blender/editors/armature/meshlaplacian.c15
-rw-r--r--source/blender/editors/armature/pose_lib.c8
-rw-r--r--source/blender/editors/armature/pose_select.c31
-rw-r--r--source/blender/editors/curve/curve_intern.h2
-rw-r--r--source/blender/editors/curve/curve_ops.c2
-rw-r--r--source/blender/editors/curve/editcurve.c93
-rw-r--r--source/blender/editors/curve/editfont.c3
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c9
-rw-r--r--source/blender/editors/include/BIF_gl.h2
-rw-r--r--source/blender/editors/include/ED_anim_api.h6
-rw-r--r--source/blender/editors/include/ED_armature.h1
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h2
-rw-r--r--source/blender/editors/include/ED_mask.h6
-rw-r--r--source/blender/editors/include/ED_sculpt.h12
-rw-r--r--source/blender/editors/include/ED_transform.h6
-rw-r--r--source/blender/editors/include/ED_view3d.h5
-rw-r--r--source/blender/editors/include/UI_interface.h103
-rw-r--r--source/blender/editors/include/UI_resources.h12
-rw-r--r--source/blender/editors/include/UI_view2d.h4
-rw-r--r--source/blender/editors/interface/interface.c119
-rw-r--r--source/blender/editors/interface/interface_draw.c20
-rw-r--r--source/blender/editors/interface/interface_handlers.c299
-rw-r--r--source/blender/editors/interface/interface_intern.h49
-rw-r--r--source/blender/editors/interface/interface_layout.c76
-rw-r--r--source/blender/editors/interface/interface_panel.c36
-rw-r--r--source/blender/editors/interface/interface_regions.c74
-rw-r--r--source/blender/editors/interface/interface_style.c18
-rw-r--r--source/blender/editors/interface/interface_templates.c78
-rw-r--r--source/blender/editors/interface/interface_widgets.c187
-rw-r--r--source/blender/editors/interface/resources.c84
-rw-r--r--source/blender/editors/interface/view2d.c12
-rw-r--r--source/blender/editors/interface/view2d_ops.c4
-rw-r--r--source/blender/editors/mask/mask_editaction.c11
-rw-r--r--source/blender/editors/mask/mask_ops.c59
-rw-r--r--source/blender/editors/mask/mask_select.c36
-rw-r--r--source/blender/editors/mask/mask_shapekey.c40
-rw-r--r--source/blender/editors/mesh/editmesh_add.c4
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c10
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c21
-rw-r--r--source/blender/editors/mesh/editmesh_select.c6
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c16
-rw-r--r--source/blender/editors/metaball/mball_edit.c36
-rw-r--r--source/blender/editors/object/object_add.c8
-rw-r--r--source/blender/editors/object/object_edit.c14
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_lattice.c82
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c7
-rw-r--r--source/blender/editors/object/object_select.c130
-rw-r--r--source/blender/editors/object/object_shapekey.c8
-rw-r--r--source/blender/editors/object/object_transform.c24
-rw-r--r--source/blender/editors/object/object_vgroup.c32
-rw-r--r--source/blender/editors/physics/particle_edit.c6
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c6
-rw-r--r--source/blender/editors/physics/rigidbody_object.c36
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_preview.c13
-rw-r--r--source/blender/editors/screen/area.c139
-rw-r--r--source/blender/editors/screen/glutil.c13
-rw-r--r--source/blender/editors/screen/screen_edit.c194
-rw-r--r--source/blender/editors/screen/screen_intern.h4
-rw-r--r--source/blender/editors/screen/screen_ops.c122
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c15
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c69
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h9
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c41
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c33
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c4
-rw-r--r--source/blender/editors/space_action/action_edit.c20
-rw-r--r--source/blender/editors/space_action/action_select.c3
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c4
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c2
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c213
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c19
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c26
-rw-r--r--source/blender/editors/space_clip/tracking_select.c28
-rw-r--r--source/blender/editors/space_file/file_draw.c42
-rw-r--r--source/blender/editors/space_file/file_intern.h10
-rw-r--r--source/blender/editors/space_file/file_ops.c137
-rw-r--r--source/blender/editors/space_file/file_panels.c2
-rw-r--r--source/blender/editors/space_file/filelist.c11
-rw-r--r--source/blender/editors/space_file/filelist.h1
-rw-r--r--source/blender/editors/space_file/filesel.c15
-rw-r--r--source/blender/editors/space_file/space_file.c1
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c12
-rw-r--r--source/blender/editors/space_graph/graph_edit.c16
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/SConscript1
-rw-r--r--source/blender/editors/space_image/image_draw.c28
-rw-r--r--source/blender/editors/space_image/image_ops.c23
-rw-r--r--source/blender/editors/space_info/info_report.c6
-rw-r--r--source/blender/editors/space_info/info_stats.c11
-rw-r--r--source/blender/editors/space_info/space_info.c3
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_node/drawnode.c18
-rw-r--r--source/blender/editors/space_node/node_add.c3
-rw-r--r--source/blender/editors/space_node/node_draw.c15
-rw-r--r--source/blender/editors/space_node/node_select.c12
-rw-r--r--source/blender/editors/space_node/node_templates.c28
-rw-r--r--source/blender/editors/space_node/space_node.c10
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c29
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c79
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c26
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c8
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c10
-rw-r--r--source/blender/editors/space_view3d/drawobject.c51
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c364
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c83
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c80
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c350
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h19
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c60
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c1419
-rw-r--r--source/blender/editors/transform/transform.c8
-rw-r--r--source/blender/editors/transform/transform.h9
-rw-r--r--source/blender/editors/transform/transform_constraints.c10
-rw-r--r--source/blender/editors/transform/transform_conversions.c44
-rw-r--r--source/blender/editors/transform/transform_generics.c10
-rw-r--r--source/blender/editors/transform/transform_manipulator.c5
-rw-r--r--source/blender/editors/transform/transform_ops.c6
-rw-r--r--source/blender/editors/transform/transform_orientations.c233
-rw-r--r--source/blender/editors/transform/transform_snap.c2
-rw-r--r--source/blender/editors/util/ed_util.c4
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt8
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c12
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c108
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c39
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c19
-rw-r--r--source/blender/freestyle/intern/application/AppConfig.h1
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp1
-rw-r--r--source/blender/freestyle/intern/geometry/BBox.h1
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRenderer.h1
-rw-r--r--source/blender/freestyle/intern/view_map/GridDensityProvider.h1
-rw-r--r--source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp6
-rw-r--r--source/blender/gpu/GPU_material.h13
-rw-r--r--source/blender/gpu/intern/gpu_draw.c2
-rw-r--r--source/blender/gpu/intern/gpu_material.c59
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl68
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h5
-rw-r--r--source/blender/imbuf/intern/IMB_indexer.h12
-rw-r--r--source/blender/imbuf/intern/anim_movie.c4
-rw-r--r--source/blender/imbuf/intern/cineon/CMakeLists.txt3
-rw-r--r--source/blender/imbuf/intern/cineon/cineonfile.h0
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c2
-rw-r--r--source/blender/imbuf/intern/cineon/dpxfile.h0
-rw-r--r--source/blender/imbuf/intern/cineon/logImageLib.h0
-rw-r--r--source/blender/imbuf/intern/colormanagement.c137
-rw-r--r--source/blender/imbuf/intern/imageprocess.c4
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp5
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.h4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp1
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_armature_types.h11
-rw-r--r--source/blender/makesdna/DNA_brush_types.h2
-rw-r--r--source/blender/makesdna/DNA_camera_types.h58
-rw-r--r--source/blender/makesdna/DNA_curve_types.h1
-rw-r--r--source/blender/makesdna/DNA_defs.h14
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h3
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h4
-rw-r--r--source/blender/makesdna/DNA_image_types.h31
-rw-r--r--source/blender/makesdna/DNA_lamp_types.h4
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h6
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h6
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h35
-rw-r--r--source/blender/makesdna/DNA_node_types.h18
-rw-r--r--source/blender/makesdna/DNA_object_types.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h102
-rw-r--r--source/blender/makesdna/DNA_screen_types.h2
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h68
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h20
-rw-r--r--source/blender/makesdna/DNA_sound_types.h22
-rw-r--r--source/blender/makesdna/DNA_space_types.h11
-rw-r--r--source/blender/makesdna/DNA_tracking_types.h6
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h44
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h3
-rw-r--r--source/blender/makesdna/DNA_world_types.h16
-rw-r--r--source/blender/makesdna/intern/makesdna.c8
-rw-r--r--source/blender/makesrna/RNA_access.h7
-rw-r--r--source/blender/makesrna/RNA_enum_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_access.c12
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c23
-rw-r--r--source/blender/makesrna/intern/rna_brush.c10
-rw-r--r--source/blender/makesrna/intern/rna_camera.c6
-rw-r--r--source/blender/makesrna/intern/rna_color.c26
-rw-r--r--source/blender/makesrna/intern/rna_define.c5
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c1
-rw-r--r--source/blender/makesrna/intern/rna_image.c3
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c19
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c65
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c43
-rw-r--r--source/blender/makesrna/intern/rna_object.c17
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c13
-rw-r--r--source/blender/makesrna/intern/rna_particle.c56
-rw-r--r--source/blender/makesrna/intern/rna_scene.c31
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c70
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c8
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c27
-rw-r--r--source/blender/makesrna/intern/rna_space.c21
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c22
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c10
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c142
-rw-r--r--source/blender/makesrna/intern/rna_wm.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c14
-rw-r--r--source/blender/modifiers/CMakeLists.txt8
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c4
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c218
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c102
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c358
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_lamp.c86
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c30
-rw-r--r--source/blender/python/SConscript7
-rw-r--r--source/blender/python/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c5
-rw-r--r--source/blender/python/bmesh/bmesh_py_geometry.c110
-rw-r--r--source/blender/python/bmesh/bmesh_py_geometry.h35
-rw-r--r--source/blender/python/generic/blf_py_api.c2
-rw-r--r--source/blender/python/intern/CMakeLists.txt12
-rw-r--r--source/blender/python/intern/bpy_app.c6
-rw-r--r--source/blender/python/intern/bpy_app_ocio.c112
-rw-r--r--source/blender/python/intern/bpy_app_ocio.h32
-rw-r--r--source/blender/python/intern/bpy_app_oiio.c112
-rw-r--r--source/blender/python/intern/bpy_app_oiio.h32
-rw-r--r--source/blender/python/intern/bpy_interface.c1
-rw-r--r--source/blender/python/intern/bpy_operator.c5
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c11
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m17
-rw-r--r--source/blender/quicktime/quicktime_export.h2
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c22
-rw-r--r--source/blender/render/intern/source/render_result.c8
-rw-r--r--source/blender/render/intern/source/render_texture.c12
-rw-r--r--source/blender/render/intern/source/shadeoutput.c93
-rw-r--r--source/blender/windowmanager/WM_api.h28
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c47
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c15
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c16
-rw-r--r--source/blender/windowmanager/intern/wm_files.c79
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c12
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c4
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c10
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c149
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c9
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c11
-rw-r--r--source/blender/windowmanager/intern/wm_window.c8
-rw-r--r--source/blender/windowmanager/wm_files.h2
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c5
-rw-r--r--source/creator/CMakeLists.txt5
-rw-r--r--source/creator/creator.c2
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp1
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp12
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp10
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp2
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h17
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp30
-rw-r--r--source/gameengine/Ketsji/KX_Light.h2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp7
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp10
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h4
-rw-r--r--source/tests/bl_rna_wiki_reference.py46
731 files changed, 20732 insertions, 13432 deletions
diff --git a/.gitignore b/.gitignore
index d4e04b64dca..e0228f27ced 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,6 @@ Desktop.ini
/blender.bin
/user-config.py
+# local patches
+/*.patch
+/*.diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5781558a61b..abca0eeac6d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,6 +254,7 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# Misc
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
+option(WITH_OPENNL "Enable use of Open Numerical Library" ON)
if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF)
@@ -297,7 +298,7 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
mark_as_advanced(WITH_ASSERT_ABORT)
-option(WITH_BOOST "Enable features depending no boost" ON)
+option(WITH_BOOST "Enable features depending on boost" ON)
if(CMAKE_COMPILER_IS_GNUCC)
option(WITH_GCC_MUDFLAP "Enable mudflap" OFF)
@@ -736,6 +737,9 @@ if(UNIX AND NOT APPLE)
if(WITH_INTERNATIONAL)
list(APPEND __boost_packages locale)
endif()
+ if(WITH_CYCLES_NETWORK)
+ list(APPEND __boost_packages serialization)
+ endif()
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
unset(__boost_packages)
if(Boost_USE_STATIC_LIBS AND WITH_BOOST_ICU)
@@ -875,7 +879,7 @@ if(UNIX AND NOT APPLE)
endif()
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
- set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++")
+ set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread")
if((NOT WITH_HEADLESS) AND (NOT WITH_GHOST_SDL))
find_package(X11 REQUIRED)
@@ -921,10 +925,10 @@ if(UNIX AND NOT APPLE)
if(CMAKE_COMPILER_IS_GNUCC)
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
# CLang is the same as GCC for now.
- elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
# Solaris CC
- elseif(CMAKE_CXX_COMPILER_ID MATCHES "SunPro")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro")
set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__")
# Intel C++ Compiler
@@ -1699,6 +1703,9 @@ elseif(APPLE)
list(APPEND BOOST_LIBRARIES boost_locale-mt)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it !
endif()
+ if(WITH_CYCLES_NETWORK)
+ list(APPEND BOOST_LIBRARIES boost_serialization-mt)
+ endif()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS)
endif()
@@ -1780,7 +1787,7 @@ elseif(APPLE)
if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "i386")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3")
set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3")
- if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller")
endif()
@@ -2027,7 +2034,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
endif()
-elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
# strange, clang complains these are not supported, but then yses them.
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
@@ -2058,6 +2065,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
+ ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_INCOMPAT_PTR_DISCARD_QUAL -Wno-incompatible-pointer-types-discards-qualifiers)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_INT_TO_VOID_POINTER_CAST -Wno-int-to-void-pointer-cast)
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_PROTOTYPES -Wno-missing-prototypes)
@@ -2239,6 +2247,9 @@ if(FIRST_RUN)
endmacro()
+ message(STATUS "C Compiler: \"${CMAKE_C_COMPILER_ID}\"")
+ message(STATUS "C++ Compiler: \"${CMAKE_CXX_COMPILER_ID}\"")
+
info_cfg_text("Build Options:")
info_cfg_option(WITH_GAMEENGINE)
info_cfg_option(WITH_PLAYER)
@@ -2305,6 +2316,9 @@ if(FIRST_RUN)
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
+ info_cfg_text("Other:")
+ info_cfg_option(WITH_OPENNL)
+
# debug
message(STATUS "HAVE_STDBOOL_H = ${HAVE_STDBOOL_H}")
diff --git a/SConstruct b/SConstruct
index 8c27424f617..3b0bf9cd831 100644
--- a/SConstruct
+++ b/SConstruct
@@ -285,6 +285,9 @@ if 'cudakernels' in B.targets:
env['WITH_BF_CYCLES_CUDA_BINARIES'] = True
env['WITH_BF_PYTHON'] = False
+# Configure paths for automated configuration test programs
+env['CONFIGUREDIR'] = os.path.abspath(os.path.normpath(os.path.join(env['BF_BUILDDIR'], "sconf_temp")))
+env['CONFIGURELOG'] = os.path.abspath(os.path.normpath(os.path.join(env['BF_BUILDDIR'], "config.log")))
#############################################################################
################### Automatic configuration for OSX ##################
@@ -293,6 +296,19 @@ if 'cudakernels' in B.targets:
if env['OURPLATFORM']=='darwin':
import commands
+ import subprocess
+
+ command = ["%s"%env['CC'], "--version"]
+ process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=False)
+ line = process.communicate()[0]
+ ver = re.search(r'[0-9]+(\.[0-9]+)+', line)
+ if ver:
+ env['CCVERSION'] = ver.group(0)
+ frontend = re.search(r'gcc', line) or re.search(r'clang', line) or re.search(r'llvm-gcc', line) or re.search(r'icc', line)
+ if frontend:
+ env['C_COMPILER_ID'] = frontend.group(0)
+
+ print B.bc.OKGREEN + "Using Compiler: " + B.bc.ENDC + env['C_COMPILER_ID'] + '-' + env['CCVERSION']
cmd = 'sw_vers -productVersion'
MAC_CUR_VER=cmd_res=commands.getoutput(cmd)
@@ -370,7 +386,9 @@ if env['OURPLATFORM']=='darwin':
#Intel Macs are CoreDuo and Up
if env['MACOSX_ARCHITECTURE'] == 'i386' or env['MACOSX_ARCHITECTURE'] == 'x86_64':
- env['REL_CCFLAGS'] = env['REL_CCFLAGS']+['-ftree-vectorize','-msse','-msse2','-msse3']
+ env['REL_CCFLAGS'] = env['REL_CCFLAGS']+['-msse','-msse2','-msse3']
+ if env['C_COMPILER_ID'] != 'clang' or (env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '5.0'):
+ env['REL_CCFLAGS'] = env['REL_CCFLAGS']+['-ftree-vectorize'] # clang xcode 4 does not accept flag
else:
env['CCFLAGS'] = env['CCFLAGS']+['-fno-strict-aliasing']
@@ -378,7 +396,7 @@ if env['OURPLATFORM']=='darwin':
if env['MACOSX_ARCHITECTURE'] == 'x86_64':
env['REL_CCFLAGS'] = env['REL_CCFLAGS']+['-mssse3']
- if env['XCODE_CUR_VER'] >= '5' and not env['CC'].split('/')[len(env['CC'].split('/'))-1][4:] >= '4.6.1':
+ if env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '5.0':
env['CCFLAGS'].append('-ftemplate-depth=1024') # only valid for clang bundled with xcode 5
# 3DconnexionClient.framework, optionally install
@@ -406,7 +424,7 @@ if env['OURPLATFORM']=='darwin':
#Defaults openMP to true if compiler handles it ( only gcc 4.6.1 and newer )
# if your compiler does not have accurate suffix you may have to enable it by hand !
if env['WITH_BF_OPENMP'] == 1:
- if env['CC'].split('/')[len(env['CC'].split('/'))-1][4:] >= '4.6.1':
+ if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6.1': # strip down to version string if any
env['WITH_BF_OPENMP'] = 1 # multithreading for fluids, cloth, sculpt and smoke
print B.bc.OKGREEN + "Using OpenMP"
else:
@@ -416,7 +434,7 @@ if env['OURPLATFORM']=='darwin':
if env['WITH_BF_CYCLES_OSL'] == 1:
OSX_OSL_LIBPATH = Dir(env.subst(env['BF_OSL_LIBPATH'])).abspath
# we need 2 variants of passing the oslexec with the force_load option, string and list type atm
- if env['CC'].split('/')[len(env['CC'].split('/'))-1][4:] >= '4.8':
+ if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.8': # strip down to version string if any
env.Append(LINKFLAGS=['-L'+OSX_OSL_LIBPATH,'-loslcomp','-loslexec','-loslquery'])
else:
env.Append(LINKFLAGS=['-L'+OSX_OSL_LIBPATH,'-loslcomp','-force_load '+ OSX_OSL_LIBPATH +'/liboslexec.a','-loslquery'])
@@ -487,6 +505,7 @@ else:
# TODO, make optional (as with CMake)
env['CPPFLAGS'].append('-DWITH_AUDASPACE')
env['CPPFLAGS'].append('-DWITH_AVI')
+env['CPPFLAGS'].append('-DWITH_OPENNL')
env['CPPFLAGS'].append('-DWITH_BOOL_COMPAT')
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc') and env['MSVC_VERSION'] == '11.0':
env['CPPFLAGS'].append('-D_ALLOW_KEYWORD_MACROS')
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 4ca7400fe44..eb72e807b2e 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -200,18 +200,22 @@ OCIO_VERSION_MIN="1.0"
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
-OPENEXR_VERSION="2.0.1"
-OPENEXR_SOURCE="http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz"
-OPENEXR_VERSION_MIN="2.0"
-ILMBASE_VERSION="2.0.1"
+OPENEXR_VERSION="2.1.0"
+OPENEXR_VERSION_MIN="2.0.1"
+#OPENEXR_SOURCE="http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz"
+OPENEXR_SOURCE="https://github.com/mont29/openexr.git"
+OPENEXR_REPO_UID="2787aa1cf652d244ed45ae124eb1553f6cff11ee"
+ILMBASE_VERSION="2.1.0"
ILMBASE_SOURCE="http://download.savannah.nongnu.org/releases/openexr/ilmbase-$ILMBASE_VERSION.tar.gz"
OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="1.1.10"
-OIIO_SOURCE="https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz"
-OIIO_VERSION_MIN="1.1"
+OIIO_VERSION="1.3.9"
+OIIO_VERSION_MIN="1.3.9"
+#OIIO_SOURCE="https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz"
+OIIO_SOURCE="https://github.com/mont29/oiio.git"
+OIIO_REPO_UID="99113d12619c90cf44721195a759674ea61f02b1"
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
@@ -224,9 +228,11 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.3.2"
+OSL_VERSION="1.4.0"
OSL_VERSION_MIN=$OSL_VERSION
-OSL_SOURCE="https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz"
+#OSL_SOURCE="https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz"
+OSL_SOURCE="https://github.com/mont29/OpenShadingLanguage.git"
+OSL_REPO_UID="175989f2610a7d54e8edfb5ace0143e28e11ac70"
OSL_FORCE_REBUILD=false
OSL_SKIP=false
@@ -855,7 +861,7 @@ clean_ILMBASE() {
compile_ILMBASE() {
# To be changed each time we make edits that would modify the compiled result!
- ilmbase_magic=6
+ ilmbase_magic=8
_init_ilmbase
# Clean install if needed!
@@ -883,24 +889,6 @@ compile_ILMBASE() {
tar -C $SRC --transform "s,(.*/?)ilmbase-[^/]*(.*),\1ILMBase-$ILMBASE_VERSION\2,x" \
-xf $_src.tar.gz
- cd $_src
-
- # XXX Ugly patching hack!
- cat << EOF | patch -p1
---- a/Half/CMakeLists.txt
-+++ b/Half/CMakeLists.txt
-@@ -47,6 +47,7 @@
-
- INSTALL ( FILES
- half.h
-+ halfExport.h
- halfFunction.h
- halfLimits.h
- DESTINATION
-EOF
-
- cd $CWD
-
fi
cd $_src
@@ -914,6 +902,9 @@ EOF
cmake_d="-D CMAKE_BUILD_TYPE=Release"
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
+ if [ $ALL_STATIC == true ]; then
+ cmake_d="$cmake_d -D BUILD_SHARED_LIBS=OFF"
+ fi
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"
@@ -958,7 +949,7 @@ clean_OPENEXR() {
compile_OPENEXR() {
# To be changed each time we make edits that would modify the compiled result!
- openexr_magic=11
+ openexr_magic=12
# Clean install if needed!
magic_compile_check openexr-$OPENEXR_VERSION $openexr_magic
@@ -983,130 +974,26 @@ compile_OPENEXR() {
if [ ! -d $_src ]; then
INFO "Downloading OpenEXR-$OPENEXR_VERSION"
mkdir -p $SRC
- wget -c $OPENEXR_SOURCE -O $_src.tar.gz
- INFO "Unpacking OpenEXR-$OPENEXR_VERSION"
- tar -C $SRC --transform "s,(.*/?)openexr[^/]*(.*),\1OpenEXR-$OPENEXR_VERSION\2,x" \
- -xf $_src.tar.gz
+# wget -c $OPENEXR_SOURCE -O $_src.tar.gz
- cd $_src
+# INFO "Unpacking OpenEXR-$OPENEXR_VERSION"
+# tar -C $SRC --transform "s,(.*/?)openexr[^/]*(.*),\1OpenEXR-$OPENEXR_VERSION\2,x" \
+# -xf $_src.tar.gz
- # XXX Ugly patching hack!
- cat << EOF | patch -p1
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -42,7 +42,7 @@
- ADD_SUBDIRECTORY ( exrmakepreview )
- ADD_SUBDIRECTORY ( exrenvmap )
- ADD_SUBDIRECTORY ( exrmultiview )
--ADD_SUBDIRECTORY ( exr2aces )
-+#ADD_SUBDIRECTORY ( exr2aces )
- ADD_SUBDIRECTORY ( exrmultipart )
-
- ##########################
-@@ -52,11 +52,11 @@
- # Documentation
- INSTALL ( FILES
- doc/TechnicalIntroduction.pdf
-- doc/TechnicalIntroduction_2.0.pdf
-+# doc/TechnicalIntroduction_2.0.pdf
- doc/ReadingAndWritingImageFiles.pdf
- doc/OpenEXRFileLayout.pdf
-- doc/OpenEXRFileLayout_2.0.pdf
-- doc/ReadingAndWritingImageFiles_2.0.pdf
-+# doc/OpenEXRFileLayout_2.0.pdf
-+# doc/ReadingAndWritingImageFiles_2.0.pdf
- doc/MultiViewOpenEXR.pdf
- DESTINATION
- ${CMAKE_INSTALL_PREFIX}/share/doc/OpenEXR-2.0.0
---- a/IlmImfFuzzTest/CMakeLists.txt
-+++ b/IlmImfFuzzTest/CMakeLists.txt
-@@ -4,7 +4,9 @@
- fuzzFile.cpp
- main.cpp
- testFuzzScanLines.cpp
-+ testFuzzDeepScanLines.cpp
- testFuzzTiles.cpp
-+ testFuzzDeepTiles.cpp
- )
-
- TARGET_LINK_LIBRARIES ( IlmImfFuzzTest IlmImf Iex Imath Half IlmThread ${PTHREAD_LIB} ${Z_LIB})
---- a/IlmImfTest/CMakeLists.txt
-+++ b/IlmImfTest/CMakeLists.txt
-@@ -19,22 +19,28 @@
- testCustomAttributes.cpp
- testDeepScanLineBasic.cpp
- testDeepScanLineHuge.cpp
-+ testDeepScanLineMultipleRead.cpp
- testDeepTiledBasic.cpp
-+ testBadTypeAttributes.cpp
- testExistingStreams.cpp
-+ testFutureProofing.cpp
- testHuf.cpp
- testInputPart.cpp
- testIsComplete.cpp
- testLineOrder.cpp
- testLut.cpp
- testMagic.cpp
- testMultiPartApi.cpp
- testMultiPartFileMixingBasic.cpp
- testMultiPartSharedAttributes.cpp
- testMultiPartThreading.cpp
- testMultiScanlinePartThreading.cpp
- testMultiTiledPartThreading.cpp
- testMultiView.cpp
- testNativeFormat.cpp
-+ testOptimized.cpp
-+ testOptimizedInterleavePatterns.cpp
-+ testPartHelper.cpp
- testPreviewImage.cpp
- testRgba.cpp
- testRgbaThreading.cpp
---- a/IlmImf/CMakeLists.txt
-+++ b/IlmImf/CMakeLists.txt
-@@ -153,18 +153,18 @@
- ImfCompositeDeepScanLine.cpp
- )
-
--ADD_LIBRARY ( IlmImf STATIC
-- \${ILMIMF_SRCS}
--)
--
--# TARGET_LINK_LIBRARIES ( IlmImf)
--
--ADD_DEPENDENCIES ( IlmImf b44ExpLogTable )
-+ADD_LIBRARY ( IlmImf STATIC \${ILMIMF_SRCS} )
-+ADD_DEPENDENCIES ( IlmImf b44ExpLogTable )
-+
-+ADD_LIBRARY ( IlmImf_dyn SHARED \${ILMIMF_SRCS} )
-+SET_TARGET_PROPERTIES ( IlmImf_dyn PROPERTIES OUTPUT_NAME IlmImf)
-+ADD_DEPENDENCIES ( IlmImf_dyn b44ExpLogTable )
-+TARGET_LINK_LIBRARIES ( IlmImf_dyn Iex Imath Half IlmThread \${Z_LIB} \${PTHREAD_LIB} )
-
- # Libraries
-
- INSTALL ( TARGETS
-- IlmImf
-+ IlmImf IlmImf_dyn
- DESTINATION
- \${CMAKE_INSTALL_PREFIX}/lib
- )
-@@ -168,6 +167,8 @@
- INSTALL ( FILES
- ${CMAKE_SOURCE_DIR}/config/OpenEXRConfig.h
- ImfForward.h
-+ ImfNamespace.h
-+ ImfPartHelper.h
- ImfExport.h
- ImfAttribute.h
- ImfBoxAttribute.h
-EOF
-
- cd $CWD
+ git clone $OPENEXR_SOURCE $_src
fi
cd $_src
+
+ # XXX For now, always update from latest repo...
+ git pull origin master
+
+ # Stick to same rev as windows' libs...
+ git checkout $OPENEXR_REPO_UID
+ git reset --hard
+
# Always refresh the whole build!
if [ -d build ]; then
rm -rf build
@@ -1125,7 +1012,7 @@ EOF
cflags="-fPIC"
fi
- cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ..
+ cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ../OpenEXR
make -j$THREADS && make install
@@ -1172,7 +1059,7 @@ clean_OIIO() {
compile_OIIO() {
# To be changed each time we make edits that would modify the compiled result!
- oiio_magic=12
+ oiio_magic=14
_init_oiio
# Clean install if needed!
@@ -1191,161 +1078,25 @@ compile_OIIO() {
if [ ! -d $_src ]; then
mkdir -p $SRC
- wget -c $OIIO_SOURCE -O "$_src.tar.gz"
+# wget -c $OIIO_SOURCE -O "$_src.tar.gz"
- INFO "Unpacking OpenImageIO-$OIIO_VERSION"
- tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
- -xf $_src.tar.gz
+# INFO "Unpacking OpenImageIO-$OIIO_VERSION"
+# tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
+# -xf $_src.tar.gz
- cd $_src
-
- # XXX Ugly patching hack!
- cat << EOF | patch -p1
---- a/src/libOpenImageIO/CMakeLists.txt
-+++ b/src/libOpenImageIO/CMakeLists.txt
-@@ -289,12 +289,12 @@
-
- add_executable (imagebuf_test imagebuf_test.cpp)
--link_ilmbase (imagebuf_test)
- target_link_libraries (imagebuf_test OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (imagebuf_test)
- add_test (unit_imagebuf imagebuf_test)
-
- add_executable (imagebufalgo_test imagebufalgo_test.cpp)
--link_ilmbase (imagebufalgo_test)
- target_link_libraries (imagebufalgo_test OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (imagebufalgo_test)
- add_test (unit_imagebufalgo imagebufalgo_test)
-
-
-@@ -340,5 +340,6 @@
-
- add_executable (imagespeed_test imagespeed_test.cpp)
- target_link_libraries (imagespeed_test OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (imagespeed_test)
- #add_test (unit_hash hash_test)
-
---- a/src/iconvert/CMakeLists.txt
-+++ b/src/iconvert/CMakeLists.txt
-@@ -1,6 +1,6 @@
- set (iconvert_srcs iconvert.cpp)
- add_executable (iconvert \${iconvert_srcs})
--link_ilmbase (iconvert)
- target_link_libraries (iconvert OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (iconvert)
- oiio_install_targets (iconvert)
-
---- a/src/idiff/CMakeLists.txt
-+++ b/src/idiff/CMakeLists.txt
-@@ -1,6 +1,6 @@
- set (idiff_srcs idiff.cpp)
- add_executable (idiff \${idiff_srcs})
--link_ilmbase (idiff)
- target_link_libraries (idiff OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (idiff)
- oiio_install_targets (idiff)
-
---- a/src/igrep/CMakeLists.txt
-+++ b/src/igrep/CMakeLists.txt
-@@ -1,6 +1,6 @@
- set (igrep_srcs igrep.cpp)
- add_executable (igrep \${igrep_srcs})
--link_ilmbase (igrep)
- target_link_libraries (igrep OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (igrep)
- oiio_install_targets (igrep)
-
---- a/src/iinfo/CMakeLists.txt
-+++ b/src/iinfo/CMakeLists.txt
-@@ -3,7 +3,7 @@
- if (MSVC)
- set_target_properties (OpenImageIO PROPERTIES LINK_FLAGS psapi.lib)
- endif (MSVC)
--link_ilmbase (iinfo)
- target_link_libraries (iinfo OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (iinfo)
- oiio_install_targets (iinfo)
-
---- a/src/maketx/CMakeLists.txt
-+++ b/src/maketx/CMakeLists.txt
-@@ -1,6 +1,6 @@
- set (maketx_srcs maketx.cpp)
- add_executable (maketx \${maketx_srcs})
--link_ilmbase (maketx)
- target_link_libraries (maketx OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (maketx)
- oiio_install_targets (maketx)
-
---- a/src/oiiotool/CMakeLists.txt
-+++ b/src/oiiotool/CMakeLists.txt
-@@ -1,6 +1,6 @@
- set (oiiotool_srcs oiiotool.cpp diff.cpp imagerec.cpp printinfo.cpp)
- add_executable (oiiotool \${oiiotool_srcs})
--link_ilmbase (oiiotool)
- target_link_libraries (oiiotool OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (oiiotool)
- oiio_install_targets (oiiotool)
-
---- a/src/testtex/CMakeLists.txt
-+++ b/src/testtex/CMakeLists.txt
-@@ -1,5 +1,5 @@
- set (testtex_srcs testtex.cpp)
- add_executable (testtex \${testtex_srcs})
--link_ilmbase (testtex)
- target_link_libraries (testtex OpenImageIO \${Boost_LIBRARIES} \${CMAKE_DL_LIBS})
-+link_ilmbase (testtex)
-
---- a/src/cmake/modules/FindIlmBase.cmake
-+++ b/src/cmake/modules/FindIlmBase.cmake
-@@ -109,11 +109,13 @@
- # Generic search paths
- set (IlmBase_generic_include_paths
- /usr/include
-+ /usr/include/\${CMAKE_LIBRARY_ARCHITECTURE}
- /usr/local/include
- /sw/include
- /opt/local/include)
- set (IlmBase_generic_library_paths
- /usr/lib
-+ /usr/lib/\${CMAKE_LIBRARY_ARCHITECTURE}
- /usr/local/lib
- /sw/lib
- /opt/local/lib)
---- a/src/cmake/modules/FindOpenEXR.cmake
-+++ b/src/cmake/modules/FindOpenEXR.cmake
-@@ -105,11 +105,13 @@
- # Generic search paths
- set (OpenEXR_generic_include_paths
- /usr/include
-+ /usr/include/\${CMAKE_LIBRARY_ARCHITECTURE}
- /usr/local/include
- /sw/include
- /opt/local/include)
- set (OpenEXR_generic_library_paths
- /usr/lib
-+ /usr/lib/\${CMAKE_LIBRARY_ARCHITECTURE}
- /usr/local/lib
- /sw/lib
- /opt/local/lib)
---- a/src/libutil/tbb_misc.cpp
-+++ b/src/libutil/tbb_misc.cpp
-@@ -44,7 +44,8 @@
-
- using namespace std;
-
--#include "tbb/tbb_machine.h"
-+//#include "tbb/tbb_machine.h"
-+#include "tbb/tbb_assert_impl.h"
-
- namespace tbb {
-
-EOF
-
- cd $CWD
+ git clone $OIIO_SOURCE $_src
fi
cd $_src
+
+ # XXX For now, always update from latest repo...
+ git pull origin master
+
+ # Stick to same rev as windows' libs...
+ git checkout $OIIO_REPO_UID
+ git reset --hard
+
# Always refresh the whole build!
if [ -d build ]; then
rm -rf build
@@ -1362,6 +1113,7 @@ EOF
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
cmake_d="$cmake_d -D OPENEXR_HOME=$INST/openexr"
+ cmake_d="$cmake_d -D OPENEXR_VERSION=$OPENEXR_VERSION"
fi
# Optional tests and cmd tools
@@ -1396,7 +1148,7 @@ EOF
cflags="-fPIC"
fi
- cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ../src
+ cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ..
make -j$THREADS && make install
make clean
@@ -1541,7 +1293,7 @@ clean_OSL() {
compile_OSL() {
# To be changed each time we make edits that would modify the compiled result!
- osl_magic=11
+ osl_magic=13
_init_osl
# Clean install if needed!
@@ -1558,18 +1310,25 @@ compile_OSL() {
if [ ! -d $_src ]; then
mkdir -p $SRC
- wget -c $OSL_SOURCE -O "$_src.tar.gz"
+# wget -c $OSL_SOURCE -O "$_src.tar.gz"
+
+# INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
+# tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
+# -xf $_src.tar.gz
+
+ git clone $OSL_SOURCE $_src
- INFO "Unpacking OpenShadingLanguage-$OSL_VERSION"
- tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \
- -xf $_src.tar.gz
- cd $_src
- #git checkout blender-fixes
- cd $CWD
fi
cd $_src
+ # XXX For now, always update from latest repo...
+ git pull origin master
+
+ # Stick to same rev as windows' libs...
+ git checkout $OSL_REPO_UID
+ git reset --hard
+
# Always refresh the whole build!
if [ -d build ]; then
rm -rf build
@@ -1584,8 +1343,8 @@ compile_OSL() {
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
if [ $_with_built_openexr == true ]; then
- #cmake_d="$cmake_d -D OPENEXR_HOME=$INST/openexr" # XXX Not used!
cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr"
+ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
fi
if [ -d $INST/boost ]; then
@@ -1608,7 +1367,7 @@ compile_OSL() {
fi
fi
- cmake $cmake_d ../src
+ cmake $cmake_d ..
make -j$THREADS && make install
make clean
@@ -2077,6 +1836,8 @@ install_DEB() {
check_package_version_ge_DEB libopenexr-dev $OPENEXR_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_DEB libopenexr-dev
+ OPENEXR_VERSION=`get_package_version_DEB libopenexr-dev`
+ ILMBASE_VERSION=$OPENEXR_VERSION
clean_OPENEXR
else
compile_OPENEXR
@@ -2486,6 +2247,8 @@ install_RPM() {
check_package_version_ge_RPM $OPENEXR_DEV $OPENEXR_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_RPM $OPENEXR_DEV
+ OPENEXR_VERSION=`get_package_version_RPM $OPENEXR_DEV`
+ ILMBASE_VERSION=$OPENEXR_VERSION
clean_OPENEXR
else
compile_OPENEXR
@@ -2782,6 +2545,8 @@ install_ARCH() {
check_package_version_ge_ARCH openexr $OPENEXR_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_ARCH openexr
+ OPENEXR_VERSION=`get_package_version_ARCH openexr`
+ ILMBASE_VERSION=$OPENEXR_VERSION
clean_OPENEXR
else
compile_OPENEXR
@@ -3025,8 +2790,10 @@ print_info() {
if [ -d $INST/openexr ]; then
_1="-D OPENEXR_ROOT_DIR=$INST/openexr"
+ _2="-D OPENEXR_VERSION=$OPENEXR_VERSION"
INFO " $_1"
- _buildargs="$_buildargs $_1"
+ INFO " $_2"
+ _buildargs="$_buildargs $_1 $_2"
fi
_1="-D WITH_CYCLES_OSL=ON"
@@ -3095,6 +2862,15 @@ print_info() {
if [ -d $INST/openexr ]; then
INFO "BF_OPENEXR = '$INST/openexr'"
+
+ _ilm_libs_ext=""
+ version_ge $OPENEXR_VERSION "2.1.0"
+ if [ $? -eq 0 ]; then
+ _ilm_libs_ext=`echo $OPENEXR_VERSION | sed -r 's/([0-9]+)\.([0-9]+).*/-\1_\2/'`
+ fi
+ INFO "BF_OPENEXR_LIB = 'Half IlmImf$_ilm_libs_ext Iex$_ilm_libs_ext Imath$_ilm_libs_ext '"
+ INFO "BF_OPENEXR_LIB_STATIC = '\${BF_OPENEXR}/lib/libHalf.a \${BF_OPENEXR}/lib/libIlmImf$_ilm_libs_ext.a \${BF_OPENEXR}/lib/libIex$_ilm_libs_ext.a \${BF_OPENEXR}/lib/libImath$_ilm_libs_ext.a \${BF_OPENEXR}/lib/libIlmThread$_ilm_libs_ext.a'"
+
fi
# XXX Always static for now :/
INFO "WITH_BF_STATICOPENEXR = True"
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 220fa08b23a..556eef88f81 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -133,12 +133,13 @@ def generic_builder(id, libdir='', branch='', rsync=False):
unpack_script = 'master_unpack.py'
f = BuildFactory()
+ if libdir != '':
+ f.addStep(lib_svn_step(libdir))
+
for submodule in ('blender-translations', 'blender-addons', 'blender-addons-contrib', 'scons'):
f.addStep(git_submodule_step(submodule))
f.addStep(git_step(branch))
f.addStep(git_submodules_update())
- if libdir != '':
- f.addStep(lib_svn_step(libdir))
f.addStep(Compile(command=['python', compile_script, id], timeout=3600))
f.addStep(Test(command=['python', test_script, id]))
diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake
index 9ea0f6c9efd..8fc2d572b62 100644
--- a/build_files/cmake/Modules/FindOpenEXR.cmake
+++ b/build_files/cmake/Modules/FindOpenEXR.cmake
@@ -34,13 +34,27 @@ IF(NOT OPENEXR_ROOT_DIR AND NOT $ENV{OPENEXR_ROOT_DIR} STREQUAL "")
SET(OPENEXR_ROOT_DIR $ENV{OPENEXR_ROOT_DIR})
ENDIF()
-SET(_openexr_FIND_COMPONENTS
- Half
- Iex
- IlmImf
- IlmThread
- Imath
-)
+if (NOT OPENEXR_VERSION)
+ SET(OPENEXR_VERSION "2.0.1")
+endif()
+if (${OPENEXR_VERSION} VERSION_LESS "2.1")
+ SET(_openexr_FIND_COMPONENTS
+ Half
+ Iex
+ IlmImf
+ IlmThread
+ Imath
+ )
+else ()
+ string(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
+ SET(_openexr_FIND_COMPONENTS
+ Half
+ Iex-${_openexr_libs_ver}
+ IlmImf-${_openexr_libs_ver}
+ IlmThread-${_openexr_libs_ver}
+ Imath-${_openexr_libs_ver}
+ )
+endif ()
SET(_openexr_SEARCH_DIRS
${OPENEXR_ROOT_DIR}
diff --git a/build_files/cmake/buildinfo.cmake b/build_files/cmake/buildinfo.cmake
index 2cc92df15e7..9b8f93584b8 100644
--- a/build_files/cmake/buildinfo.cmake
+++ b/build_files/cmake/buildinfo.cmake
@@ -8,14 +8,26 @@ set(MY_WC_BRANCH "unknown")
set(MY_WC_COMMIT_TIMESTAMP 0)
# Guess if this is a SVN working copy and then look up the revision
-if(EXISTS ${SOURCE_DIR}/.git/)
- # The FindSubversion.cmake module is part of the standard distribution
+if(EXISTS ${SOURCE_DIR}/.git)
+ # The FindGit.cmake module is part of the standard distribution
include(FindGit)
if(GIT_FOUND)
- execute_process(COMMAND git rev-parse --short HEAD
+ message(STATUS "-- Found Git: ${GIT_EXECUTABLE}")
+
+ execute_process(COMMAND git rev-parse --short @{u}
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE MY_WC_HASH
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
+
+ if (MY_WC_HASH STREQUAL "")
+ # Local branch, not set to upstream.
+ # Well, let's use HEAD for now
+ execute_process(COMMAND git rev-parse --short HEAD
+ WORKING_DIRECTORY ${SOURCE_DIR}
+ OUTPUT_VARIABLE MY_WC_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ endif()
execute_process(COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${SOURCE_DIR}
@@ -44,7 +56,8 @@ if(EXISTS ${SOURCE_DIR}/.git/)
execute_process(COMMAND git log @{u}..
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE _git_unpushed_log
- OUTPUT_STRIP_TRAILING_WHITESPACE)
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
if(NOT _git_unpushed_log STREQUAL "")
set(MY_WC_BRANCH "${MY_WC_BRANCH} (modified)")
endif()
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index e9ff31fc6c5..ca9aadd649c 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -45,6 +45,7 @@ set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO 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)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index e7e88ad5703..0bf31f7e678 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -530,7 +530,7 @@ macro(remove_strict_flags)
add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
endif()
- if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
remove_cc_flag("-Wunused-parameter")
remove_cc_flag("-Wunused-variable")
remove_cc_flag("-Werror=[^ ]+")
@@ -555,7 +555,7 @@ macro(remove_strict_flags_file
foreach(_SOURCE ${ARGV})
if(CMAKE_COMPILER_IS_GNUCC OR
- (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
+ (CMAKE_C_COMPILER_ID MATCHES "Clang"))
set_source_files_properties(${_SOURCE}
PROPERTIES
diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake
index 8a534bc530e..ad309b0a0c8 100644
--- a/build_files/cmake/packaging.cmake
+++ b/build_files/cmake/packaging.cmake
@@ -20,25 +20,29 @@ SET(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}")
# Get the build revision, note that this can get out-of-sync, so for packaging run cmake first.
-include(FindSubversion)
-set(MY_WC_REVISION "unknown")
-if(EXISTS ${CMAKE_SOURCE_DIR}/.svn/)
- if(Subversion_FOUND)
- Subversion_WC_INFO(${CMAKE_SOURCE_DIR} MY)
+set(MY_WC_HASH "unknown")
+if(EXISTS ${CMAKE_SOURCE_DIR}/.git/)
+ include(FindGit)
+ if(GIT_FOUND)
+ message(STATUS "-- Found Git: ${GIT_EXECUTABLE}")
+ execute_process(COMMAND git rev-parse --short @{u}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE MY_WC_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
endif()
-set(BUILD_REV ${MY_WC_REVISION})
+set(BUILD_REV ${MY_WC_HASH})
# Force Package Name
-set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-1.r${BUILD_REV}-${CMAKE_SYSTEM_PROCESSOR})
+set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-1.${BUILD_REV}-${CMAKE_SYSTEM_PROCESSOR})
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
# RPM packages
include(build_files/cmake/RpmBuild.cmake)
if(RPMBUILD_FOUND AND NOT WIN32)
set(CPACK_GENERATOR "RPM")
- set(CPACK_RPM_PACKAGE_RELEASE "1.r${BUILD_REV}")
+ set(CPACK_RPM_PACKAGE_RELEASE "1.${BUILD_REV}")
set(CPACK_SET_DESTDIR "true")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
set(CPACK_PACKAGE_RELOCATABLE "false")
@@ -75,14 +79,14 @@ endmacro()
if(APPLE)
add_package_archive(
- "${PROJECT_NAME}-${BLENDER_VERSION}-r${BUILD_REV}-OSX-${CMAKE_OSX_ARCHITECTURES}"
+ "${PROJECT_NAME}-${BLENDER_VERSION}-${BUILD_REV}-OSX-${CMAKE_OSX_ARCHITECTURES}"
"zip")
elseif(UNIX)
# platform name could be tweaked, to include glibc, and ensure processor is correct (i386 vs i686)
string(TOLOWER ${CMAKE_SYSTEM_NAME} PACKAGE_SYSTEM_NAME)
add_package_archive(
- "${PROJECT_NAME}-${BLENDER_VERSION}-r${BUILD_REV}-${PACKAGE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}"
+ "${PROJECT_NAME}-${BLENDER_VERSION}-${BUILD_REV}-${PACKAGE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}"
"tar.bz2")
endif()
diff --git a/build_files/scons/config/Modules/FindPython.py b/build_files/scons/config/Modules/FindPython.py
index 03e15349da5..03c9d5487d0 100644
--- a/build_files/scons/config/Modules/FindPython.py
+++ b/build_files/scons/config/Modules/FindPython.py
@@ -37,8 +37,6 @@ def FindPython():
_libpath_arch = os.path.join(python, "lib", _arch) # No lib64 stuff with recent deb-like distro afaik...
_libs = ["libpython" + version + abi_flags + ext for ext in (".so", ".a")]
for l in _libs:
- print os.path.join(libpath, l), os.path.exists(os.path.join(libpath, l))
- print os.path.join(_libpath_arch, l), os.path.exists(os.path.join(_libpath_arch, l))
if not os.path.exists(os.path.join(libpath, l)) and os.path.exists(os.path.join(_libpath_arch, l)):
libpath_arch = os.path.join(libpath, _arch)
break
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 743131ab32e..ce2d07f782c 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -247,7 +247,7 @@ C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wunused-par
CC_WARN = ['-Wall']
CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
-LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++']
+LLIBS = ['util', 'c', 'm', 'dl', 'pthread']
BF_PROFILE = False
BF_PROFILE_CCFLAGS = ['-pg','-g']
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 894c8dbca25..32918519cd4 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -419,9 +419,19 @@ def buildinfo(lenv, build_type):
build_commit_timestamp = '0'
build_branch = 'unknown'
else:
- build_hash = os.popen('git rev-parse --short HEAD').read().strip()
+ import subprocess
+ no_upstream = False
+
+ process = subprocess.Popen(['git', 'rev-parse', '--short', '@{u}'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ build_hash, stderr = process.communicate()
+ build_hash = build_hash.strip()
build_branch = os.popen('git rev-parse --abbrev-ref HEAD').read().strip()
+ if build_hash == '':
+ build_hash = os.popen('git rev-parse --short HEAD').read().strip()
+ no_upstream = True
+
# ## Check for local modifications
has_local_changes = False
@@ -431,7 +441,7 @@ def buildinfo(lenv, build_type):
if changed_files:
has_local_changes = True
- else:
+ elif no_upstream == False:
unpushed_log = os.popen('git log @{u}..').read().strip()
has_local_changes = unpushed_log != ''
@@ -720,7 +730,7 @@ def AppIt(target=None, source=None, env=None):
commands.getoutput(cmd)
cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
commands.getoutput(cmd)
- if env['CC'].split('/')[len(env['CC'].split('/'))-1][4:] >= '4.6.1': # for correct errorhandling with gcc <= 4.6.1 we need the gcc.dylib and gomp.dylib to link, thus distribute in app-bundle
+ if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6.1': # for correct errorhandling with gcc >= 4.6.1 we need the gcc.dylib and gomp.dylib to link, thus distribute in app-bundle
print "Bundling libgcc and libgomp"
instname = env['BF_CXX']
cmd = 'ditto --arch %s %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgcc
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index f7a5eb8cf06..715d9220682 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -179,7 +179,7 @@ def validate_arguments(args, bc):
'BF_PROFILE_CFLAGS', 'BF_PROFILE_CCFLAGS', 'BF_PROFILE_CXXFLAGS', 'BF_PROFILE_LINKFLAGS',
'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS',
'C_WARN', 'CC_WARN', 'CXX_WARN',
- 'LLIBS', 'PLATFORM_LINKFLAGS', 'MACOSX_ARCHITECTURE', 'MACOSX_SDK', 'XCODE_CUR_VER',
+ 'LLIBS', 'PLATFORM_LINKFLAGS', 'MACOSX_ARCHITECTURE', 'MACOSX_SDK', 'XCODE_CUR_VER', 'C_COMPILER_ID',
'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET'
]
@@ -504,6 +504,7 @@ def read_opts(env, cfg, args):
('MACOSX_SDK', 'Set OS X SDK', ''),
('XCODE_CUR_VER', 'Detect XCode version', ''),
('MACOSX_DEPLOYMENT_TARGET', 'Detect OS X target version', ''),
+ ('C_COMPILER_ID', 'Detect the resolved compiler', ''),
(BoolVariable('BF_PROFILE', 'Add profiling information if true', False)),
('BF_PROFILE_CFLAGS', 'C only profiling flags', []),
diff --git a/doc/python_api/examples/bpy.types.UIList.1.py b/doc/python_api/examples/bpy.types.UIList.1.py
index 88f6b0999cd..92b115b2af4 100644
--- a/doc/python_api/examples/bpy.types.UIList.1.py
+++ b/doc/python_api/examples/bpy.types.UIList.1.py
@@ -32,11 +32,14 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
ma = slot.material
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- # You should always start your row layout by a label (icon + text), this will also make the row easily
- # selectable in the list!
+ # You should always start your row layout by a label (icon + text), or a non-embossed text field,
+ # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
- layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ if ma:
+ layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
+ else:
+ layout.label(text="", translate=False, icon_value=icon)
# And now we can add other UI stuff...
# Here, we add nodes info if this material uses (old!) shading nodes.
if ma and not context.scene.render.use_shading_nodes:
diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py
index 4e30e6895d6..feed263b2e7 100644
--- a/doc/python_api/examples/bpy.types.UIList.2.py
+++ b/doc/python_api/examples/bpy.types.UIList.2.py
@@ -49,9 +49,9 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
col = layout.column()
col.enabled = False
col.alignment = 'LEFT'
- col.label(text=vgroup.name, translate=False, icon_value=icon)
+ col.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
else:
- layout.label(text=vgroup.name, translate=False, icon_value=icon)
+ layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
elif self.layout_type in {'GRID'}:
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 5d699637eb7..af4852d6ab1 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
@@ -151,11 +151,17 @@ base class --- :class:`SCA_IObject`
visibility flag.
:type: boolean
-
+
.. note::
-
+
Game logic will still run for invisible objects.
+ .. attribute:: record_animation
+
+ Record animation for this object.
+
+ :type: boolean
+
.. attribute:: color
The object color of the object. [r, g, b, a]
diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst
index ce7c09ad3a1..9dccd4e72ae 100644
--- a/doc/python_api/rst/include__bmesh.rst
+++ b/doc/python_api/rst/include__bmesh.rst
@@ -9,6 +9,7 @@ Submodules:
* :mod:`bmesh.ops`
* :mod:`bmesh.types`
* :mod:`bmesh.utils`
+* :mod:`bmesh.geometry`
Intro
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index e95fa6fef35..a8128633569 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -256,6 +256,7 @@ else:
"bmesh.ops",
"bmesh.types",
"bmesh.utils",
+ "bmesh.geometry",
"bpy.app",
"bpy.app.handlers",
"bpy.app.translations",
@@ -384,12 +385,12 @@ MODULE_GROUPING = {
blender_version_strings = [str(v) for v in bpy.app.version]
# converting bytes to strings, due to #30154
-BLENDER_REVISION = str(bpy.app.build_revision, 'utf_8')
+BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
BLENDER_DATE = str(bpy.app.build_date, 'utf_8')
BLENDER_VERSION_DOTS = ".".join(blender_version_strings) # '2.62.1'
if BLENDER_REVISION != "Unknown":
- BLENDER_VERSION_DOTS += " r" + BLENDER_REVISION # '2.62.1 r44584'
+ BLENDER_VERSION_DOTS += " " + BLENDER_REVISION # '2.62.1 SHA1'
BLENDER_VERSION_PATH = "_".join(blender_version_strings) # '2_62_1'
if bpy.app.version_cycle == "release":
@@ -1768,6 +1769,7 @@ def write_rst_importable_modules(basepath):
"bmesh" : "BMesh Module",
"bmesh.types" : "BMesh Types",
"bmesh.utils" : "BMesh Utilities",
+ "bmesh.geometry" : "BMesh Geometry Utilities",
"bpy.app" : "Application Data",
"bpy.app.handlers" : "Application Handlers",
"bpy.app.translations" : "Application Translations",
diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh
index 9e069cb0540..5b9af77a58c 100755
--- a/doc/python_api/sphinx_doc_gen.sh
+++ b/doc/python_api/sphinx_doc_gen.sh
@@ -17,7 +17,7 @@ DO_OUT_PDF=false
BLENDER="./blender.bin"
SSH_USER="ideasman42"
-SSH_HOST=$SSH_USER"@emo.blender.org"
+SSH_HOST=$SSH_USER"@blender.org"
SSH_UPLOAD="/data/www/vhosts/www.blender.org/documentation" # blender_python_api_VERSION, added after
# ----------------------------------------------------------------------------
@@ -99,18 +99,18 @@ fi
if $DO_UPLOAD ; then
cp $SPHINXBASE/sphinx-out/contents.html $SPHINXBASE/sphinx-out/index.html
- ssh $SSH_USER@emo.blender.org 'rm -rf '$SSH_UPLOAD_FULL'/*'
+ ssh $SSH_USER@blender.org 'rm -rf '$SSH_UPLOAD_FULL'/*'
rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/* $SSH_HOST:$SSH_UPLOAD_FULL/
## symlink the dir to a static URL
- #ssh $SSH_USER@emo.blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc'
+ #ssh $SSH_USER@blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc'
# better redirect
- ssh $SSH_USER@emo.blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/250PythonDoc/index.html'
+ ssh $SSH_USER@blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/250PythonDoc/index.html'
# redirect for release only so wiki can point here
if [ "$blender_version_cycle" == "release" ] ; then
- ssh $SSH_USER@emo.blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/blender_python_api/index.html'
+ ssh $SSH_USER@blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/blender_python_api/index.html'
fi
if $DO_OUT_PDF ; then
diff --git a/extern/carve/bundle.sh b/extern/carve/bundle.sh
index c80bf645077..05967d6131d 100755
--- a/extern/carve/bundle.sh
+++ b/extern/carve/bundle.sh
@@ -30,8 +30,6 @@ sources=`find ./lib -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' |
headers=`find ./lib -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t/' | sort -d`
includes=`find ./include -type f -iname '*.h' -or -iname '*.hpp' | sed -r 's/^\.\//\t/' | sort -d`
-mkdir -p include/carve/external/boost
-cp patches/files/random.hpp include/carve/external/boost/random.hpp
cp patches/files/config.h include/carve/config.h
cat > CMakeLists.txt << EOF
diff --git a/extern/carve/files.txt b/extern/carve/files.txt
index 1084c7f5c41..f7da6038692 100644
--- a/extern/carve/files.txt
+++ b/extern/carve/files.txt
@@ -25,7 +25,6 @@ include/carve/win32.h
include/carve/edge_impl.hpp
include/carve/carve.hpp
include/carve/polyline.hpp
-include/carve/config.h
include/carve/face_decl.hpp
include/carve/matrix.hpp
include/carve/classification.hpp
@@ -67,7 +66,6 @@ include/carve/djset.hpp
include/carve/vertex_decl.hpp
include/carve/csg_triangulator.hpp
include/carve/poly.hpp
-include/carve/external/boost/random.hpp
include/carve/timing.hpp
include/carve/octree_decl.hpp
include/carve/pointset_decl.hpp
diff --git a/extern/carve/include/carve/aabb.hpp b/extern/carve/include/carve/aabb.hpp
index 20ee028aa45..c2fb2f6075f 100644
--- a/extern/carve/include/carve/aabb.hpp
+++ b/extern/carve/include/carve/aabb.hpp
@@ -120,6 +120,12 @@ namespace carve {
template<unsigned ndim>
std::ostream &operator<<(std::ostream &o, const aabb<ndim> &a);
+ template<unsigned ndim>
+ double distance2(const aabb<3> &a, const vector<ndim> &v);
+
+ template<unsigned ndim>
+ double distance(const aabb<3> &a, const vector<ndim> &v);
+
template<unsigned ndim, typename obj_t>
diff --git a/extern/carve/include/carve/aabb_impl.hpp b/extern/carve/include/carve/aabb_impl.hpp
index ccdddef160b..9564885ea2a 100644
--- a/extern/carve/include/carve/aabb_impl.hpp
+++ b/extern/carve/include/carve/aabb_impl.hpp
@@ -316,6 +316,23 @@ namespace carve {
return o;
}
+ template<unsigned ndim>
+ double distance2(const aabb<3> &a, const vector<ndim> &v) {
+ double d2 = 0.0;
+ for (unsigned i = 0; i < ndim; ++i) {
+ double d = ::fabs(v.v[i] - a.pos.v[i]) - a.extent.v[i];
+ if (d > 0.0) {
+ d2 += d * d;
+ }
+ }
+ return d2;
+ }
+
+ template<unsigned ndim>
+ double distance(const aabb<3> &a, const vector<ndim> &v) {
+ return ::sqrt(distance2(a, v));
+ }
+
template<>
inline bool aabb<3>::intersects(const ray<3> &ray) const {
vector<3> t = pos - ray.v;
diff --git a/extern/carve/include/carve/csg.hpp b/extern/carve/include/carve/csg.hpp
index b098cd86cef..92b03a4c33f 100644
--- a/extern/carve/include/carve/csg.hpp
+++ b/extern/carve/include/carve/csg.hpp
@@ -87,6 +87,11 @@ namespace carve {
const meshset_t::face_t * /* orig_face */,
bool /* flipped */) {
}
+ virtual void edgeDivision(const meshset_t::edge_t * /* orig_edge */,
+ size_t /* orig_edge_idx */,
+ const meshset_t::vertex_t * /* v1 */,
+ const meshset_t::vertex_t * /* v2 */) {
+ }
virtual ~Hook() {
}
@@ -103,11 +108,13 @@ namespace carve {
RESULT_FACE_HOOK = 0,
PROCESS_OUTPUT_FACE_HOOK = 1,
INTERSECTION_VERTEX_HOOK = 2,
- HOOK_MAX = 3,
+ EDGE_DIVISION_HOOK = 3,
+ HOOK_MAX = 4,
RESULT_FACE_BIT = 0x0001,
PROCESS_OUTPUT_FACE_BIT = 0x0002,
- INTERSECTION_VERTEX_BIT = 0x0004
+ INTERSECTION_VERTEX_BIT = 0x0004,
+ EDGE_DIVISION_BIT = 0x0008
};
std::vector<std::list<Hook *> > hooks;
@@ -125,6 +132,11 @@ namespace carve {
const meshset_t::face_t *orig_face,
bool flipped);
+ void edgeDivision(const meshset_t::edge_t *orig_edge,
+ size_t orig_edge_idx,
+ const meshset_t::vertex_t *v1,
+ const meshset_t::vertex_t *v2);
+
void registerHook(Hook *hook, unsigned hook_bits);
void unregisterHook(Hook *hook);
diff --git a/extern/carve/include/carve/debug_hooks.hpp b/extern/carve/include/carve/debug_hooks.hpp
index 9ef7fc83573..d942a823371 100644
--- a/extern/carve/include/carve/debug_hooks.hpp
+++ b/extern/carve/include/carve/debug_hooks.hpp
@@ -35,11 +35,11 @@ void map_histogram(std::ostream &out, const MAP &map) {
}
hist[n]++;
}
- int total = map.size();
+ int total = (int)map.size();
std::string bar(50, '*');
for (size_t i = 0; i < hist.size(); i++) {
if (hist[i] > 0) {
- out << std::setw(5) << i << " : " << std::setw(5) << hist[i] << " " << bar.substr(50 - hist[i] * 50 / total) << std::endl;
+ out << std::setw(5) << i << " : " << std::setw(5) << hist[i] << " " << bar.substr((size_t)(50 - hist[i] * 50 / total)) << std::endl;
}
}
}
diff --git a/extern/carve/include/carve/face_impl.hpp b/extern/carve/include/carve/face_impl.hpp
index 771ba761111..e1a9ed306a2 100644
--- a/extern/carve/include/carve/face_impl.hpp
+++ b/extern/carve/include/carve/face_impl.hpp
@@ -42,7 +42,9 @@ namespace carve {
template<unsigned ndim>
template<typename iter_t>
Face<ndim> *Face<ndim>::init(const Face<ndim> *base, iter_t vbegin, iter_t vend, bool flipped) {
- vertices.reserve(std::distance(vbegin, vend));
+ CARVE_ASSERT(vbegin < vend);
+
+ vertices.reserve((size_t)std::distance(vbegin, vend));
if (flipped) {
std::reverse_copy(vbegin, vend, std::back_inserter(vertices));
diff --git a/extern/carve/include/carve/geom.hpp b/extern/carve/include/carve/geom.hpp
index 421083e3e3c..360f14f2607 100644
--- a/extern/carve/include/carve/geom.hpp
+++ b/extern/carve/include/carve/geom.hpp
@@ -138,6 +138,9 @@ namespace carve {
template<unsigned ndim, typename iter_t, typename adapt_t>
void bounds(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &min, vector<ndim> &max);
+ template<unsigned ndim, typename iter_t>
+ void centroid(iter_t begin, iter_t end, vector<ndim> &c);
+
template<unsigned ndim, typename iter_t, typename adapt_t>
void centroid(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &c);
@@ -300,6 +303,7 @@ namespace carve {
aabb<ndim> getAABB() const;
+ tri() { }
tri(vector_t _v[3]);
tri(const vector_t &a, const vector_t &b, const vector_t &c);
diff --git a/extern/carve/include/carve/geom2d.hpp b/extern/carve/include/carve/geom2d.hpp
index 731e22919b6..ef10b68725e 100644
--- a/extern/carve/include/carve/geom2d.hpp
+++ b/extern/carve/include/carve/geom2d.hpp
@@ -347,7 +347,7 @@ namespace carve {
PolyInclusionInfo pointInPoly(const std::vector<T> &points, adapt_t adapt, const P2 &p) {
P2Vector::size_type l = points.size();
for (unsigned i = 0; i < l; i++) {
- if (equal(adapt(points[i]), p)) return PolyInclusionInfo(POINT_VERTEX, i);
+ if (equal(adapt(points[i]), p)) return PolyInclusionInfo(POINT_VERTEX, (int)i);
}
for (unsigned i = 0; i < l; i++) {
@@ -358,7 +358,7 @@ namespace carve {
std::min(adapt(points[i]).y, adapt(points[j]).y) - EPSILON < p.y &&
std::max(adapt(points[i]).y, adapt(points[j]).y) + EPSILON > p.y &&
distance2(carve::geom::rayThrough(adapt(points[i]), adapt(points[j])), p) < EPSILON2) {
- return PolyInclusionInfo(POINT_EDGE, i);
+ return PolyInclusionInfo(POINT_EDGE, (int)i);
}
}
diff --git a/extern/carve/include/carve/geom3d.hpp b/extern/carve/include/carve/geom3d.hpp
index faeb565b922..fda43cc2b88 100644
--- a/extern/carve/include/carve/geom3d.hpp
+++ b/extern/carve/include/carve/geom3d.hpp
@@ -45,56 +45,57 @@ namespace carve {
template<typename iter_t, typename adapt_t>
bool fitPlane(iter_t begin, iter_t end, adapt_t adapt, Plane &plane) {
- Vector centroid;
- carve::geom::centroid(begin, end, adapt, centroid);
- iter_t i;
+ std::vector<Vector> p;
+ for (; begin != end; ++begin) {
+ p.push_back(adapt(*begin));
+ }
- Vector n = Vector::ZERO();
- Vector v;
- Vector p1, p2, p3, c1, c2;
- if (begin == end) return false;
+ if (p.size() < 3) {
+ return false;
+ }
- i = begin;
- p1 = c1 = adapt(*i); if (++i == end) return false;
- p2 = c2 = adapt(*i); if (++i == end) return false;
+ Vector C;
+ carve::geom::centroid(p.begin(), p.end(), C);
-#if defined(CARVE_DEBUG)
- size_t N = 2;
-#endif
- do {
- p3 = adapt(*i);
- v = cross(p3 - p2, p1 - p2);
- if (v.v[largestAxis(v)]) v.negate();
- n += v;
- p1 = p2; p2 = p3;
-#if defined(CARVE_DEBUG)
- ++N;
-#endif
- } while (++i != end);
+ Vector n;
+
+ if (p.size() == 3) {
+ n = cross(p[1] - p[0], p[2] - p[0]);
+ } else {
+ const size_t N = p.size();
+
+ n = cross(p[N-1] - C, p[0] - C);
+ if (n < Vector::ZERO()) n.negate();
+ for (size_t i = 1; i < p.size(); ++i) {
+ Vector v = cross(p[i] - C, p[i-1] - C);
+ if (v < Vector::ZERO()) v.negate();
+ n += v;
+ }
+ }
- p1 = p2; p2 = p3; p3 = c1;
- v = cross(p3 - p2, p1 - p2);
- if (v.v[largestAxis(v)]) v.negate();
- n += v;
+ double l = n.length();
- p1 = p2; p2 = p3; p3 = c2;
- v = cross(p3 - p2, p1 - p2);
- if (v.v[largestAxis(v)]) v.negate();
- n += v;
+ if (l == 0.0) {
+ n.x = 1.0;
+ n.y = 0.0;
+ n.z = 0.0;
+ } else {
+ n.normalize();
+ }
- n.normalize();
plane.N = n;
- plane.d = -dot(n, centroid);
+ plane.d = -dot(n, C);
+
#if defined(CARVE_DEBUG)
- if (N > 3) {
- std::cerr << "N = " << N << " fitted distance:";
- for (i = begin; i != end; ++i) {
- Vector p = adapt(*i);
- std::cerr << " {" << p << "} " << distance(plane, p);
+ if (p.size() > 3) {
+ std::cerr << "N-gon with " << p.size() << " vertices: fitted distance:";
+ for (size_t i = 0; i < N; ++i) {
+ std::cerr << " {" << p[i] << "} " << distance(plane, p[i]);
}
std::cerr << std::endl;
}
#endif
+
return true;
}
diff --git a/extern/carve/include/carve/geom_impl.hpp b/extern/carve/include/carve/geom_impl.hpp
index 044655b6c07..c4b6a9d5491 100644
--- a/extern/carve/include/carve/geom_impl.hpp
+++ b/extern/carve/include/carve/geom_impl.hpp
@@ -26,13 +26,26 @@ namespace carve {
template<unsigned ndim>
double vector<ndim>::length2() const { return dot(*this, *this); }
+
template<unsigned ndim>
double vector<ndim>::length() const { return sqrt(dot(*this, *this)); }
template<unsigned ndim>
- vector<ndim> &vector<ndim>::normalize() { *this /= length(); return *this; }
+ vector<ndim> &vector<ndim>::normalize() {
+#if defined(CARVE_DEBUG)
+ CARVE_ASSERT(length() > 0.0);
+#endif
+ *this /= length();
+ return *this;
+ }
+
template<unsigned ndim>
- vector<ndim> vector<ndim>::normalized() const { return *this / length(); }
+ vector<ndim> vector<ndim>::normalized() const {
+#if defined(CARVE_DEBUG)
+ CARVE_ASSERT(length() > 0.0);
+#endif
+ return *this / length();
+ }
template<unsigned ndim>
bool vector<ndim>::exactlyZero() const {
@@ -289,24 +302,24 @@ namespace carve {
template<unsigned ndim>
int smallestAxis(const vector<ndim> &a) {
- int x = 0;
- double y = fabs(a[0]);
+ int idx = 0;
+ double lo = fabs(a[0]);
for (unsigned i = 1; i < ndim; ++i) {
- double z = fabs(a[i]);
- if (z <= y) { y = z; x = i; }
+ double val = fabs(a[i]);
+ if (val <= lo) { lo = val; idx = (int)i; }
}
- return x;
+ return idx;
}
template<unsigned ndim>
int largestAxis(const vector<ndim> &a) {
- int x = 0;
- double y = fabs(a[0]);
+ int idx = 0;
+ double hi = fabs(a[0]);
for (unsigned i = 1; i < ndim; ++i) {
- double z = fabs(a[i]);
- if (z > y) { y = z; x = i; }
+ double val = fabs(a[i]);
+ if (val > hi) { hi = val; idx = (int)i; }
}
- return x;
+ return idx;
}
template<unsigned ndim>
@@ -365,11 +378,19 @@ namespace carve {
}
}
+ template<unsigned ndim, typename iter_t>
+ void centroid(iter_t begin, iter_t end, vector<ndim> &c) {
+ c.setZero();
+ int n = 0;
+ for (; begin != end; ++begin, ++n) { c += *begin; }
+ c /= double(n);
+ }
+
template<unsigned ndim, typename iter_t, typename adapt_t>
void centroid(iter_t begin, iter_t end, adapt_t adapt, vector<ndim> &c) {
c.setZero();
int n = 0;
- while (begin != end) { c += adapt(*begin++); ++n; }
+ for (; begin != end; ++begin, ++n) { c += adapt(*begin); }
c /= double(n);
}
diff --git a/extern/carve/include/carve/interpolator.hpp b/extern/carve/include/carve/interpolator.hpp
index e1555105435..f8162e52f39 100644
--- a/extern/carve/include/carve/interpolator.hpp
+++ b/extern/carve/include/carve/interpolator.hpp
@@ -89,6 +89,8 @@ namespace carve {
return result;
}
+
+
template<typename iter_t,
typename adapt_t,
typename val_t,
@@ -113,6 +115,8 @@ namespace carve {
return mod(v);
}
+
+
template<typename iter_t,
typename adapt_t,
typename val_t>
@@ -124,6 +128,8 @@ namespace carve {
double y) {
return interp(begin, end, adapt, vals, x, y, identity_t<val_t>());
}
+
+
template<typename vertex_t,
typename adapt_t,
@@ -138,6 +144,8 @@ namespace carve {
return interp(poly.begin(), poly.end(), adapt, vals, x, y, mod);
}
+
+
template<typename vertex_t,
typename adapt_t,
typename val_t>
@@ -149,6 +157,8 @@ namespace carve {
return interp(poly.begin(), poly.end(), adapt, vals, x, y, identity_t<val_t>());
}
+
+
template<typename val_t,
typename mod_t>
val_t interp(const std::vector<carve::geom2d::P2> &poly,
@@ -166,6 +176,8 @@ namespace carve {
return mod(v);
}
+
+
template<typename val_t>
val_t interp(const std::vector<carve::geom2d::P2> &poly,
const std::vector<val_t> &vals,
@@ -174,90 +186,122 @@ namespace carve {
return interp(poly, vals, x, y, identity_t<val_t>());
}
+
+
class Interpolator {
public:
- virtual void interpolate(const carve::mesh::MeshSet<3>::face_t *new_face,
- const carve::mesh::MeshSet<3>::face_t *orig_face,
- bool flipped) =0;
-
- Interpolator() {
- }
+ typedef carve::mesh::MeshSet<3> meshset_t;
- virtual ~Interpolator() {
- }
+ protected:
+ friend struct Hook;
- class Hook : public carve::csg::CSG::Hook {
+ struct Hook : public carve::csg::CSG::Hook {
+ const carve::csg::CSG &csg;
Interpolator *interpolator;
- public:
- virtual void resultFace(const carve::mesh::MeshSet<3>::face_t *new_face,
- const carve::mesh::MeshSet<3>::face_t *orig_face,
+
+ virtual unsigned hookBits() const {
+ return carve::csg::CSG::Hooks::RESULT_FACE_BIT;
+ }
+ virtual void resultFace(const meshset_t::face_t *new_face,
+ const meshset_t::face_t *orig_face,
bool flipped) {
- interpolator->interpolate(new_face, orig_face, flipped);
+ interpolator->resultFace(csg, new_face, orig_face, flipped);
+ }
+ virtual void processOutputFace(std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
+ interpolator->processOutputFace(csg, new_faces, orig_face, flipped);
+ }
+ virtual void edgeDivision(const meshset_t::edge_t *orig_edge,
+ size_t orig_edge_idx,
+ const meshset_t::vertex_t *v1,
+ const meshset_t::vertex_t *v2) {
+ interpolator->edgeDivision(csg, orig_edge, orig_edge_idx, v1, v2);
}
- Hook(Interpolator *_interpolator) : interpolator(_interpolator) {
+ Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : interpolator(_interpolator), csg(_csg) {
}
virtual ~Hook() {
}
};
+ virtual Hook *makeHook(carve::csg::CSG &csg) {
+ return new Hook(this, csg);
+ }
+
+ virtual void resultFace(const carve::csg::CSG &csg,
+ const meshset_t::face_t *new_face,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
+ }
+
+ virtual void processOutputFace(const carve::csg::CSG &csg,
+ std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
+ }
+
+ virtual void edgeDivision(const carve::csg::CSG &csg,
+ const meshset_t::edge_t *orig_edge,
+ size_t orig_edge_idx,
+ const meshset_t::vertex_t *v1,
+ const meshset_t::vertex_t *v2) {
+ }
+
+ public:
+
+ Interpolator() {
+ }
+
+ virtual ~Interpolator() {
+ }
+
void installHooks(carve::csg::CSG &csg) {
- csg.hooks.registerHook(new Hook(this), carve::csg::CSG::Hooks::RESULT_FACE_BIT);
+ Hook *hook = makeHook(csg);
+ csg.hooks.registerHook(hook, hook->hookBits());
}
};
+
+
template<typename attr_t>
class FaceVertexAttr : public Interpolator {
+ public:
+ typedef std::pair<const meshset_t::face_t *, unsigned> key_t;
protected:
- struct fv_hash {
- size_t operator()(const std::pair<const carve::mesh::MeshSet<3>::face_t *, unsigned> &v) const {
+ struct key_hash {
+ size_t operator()(const key_t &v) const {
return size_t(v.first) ^ size_t(v.second);
}
};
- typedef std::unordered_map<const carve::mesh::MeshSet<3>::vertex_t *, attr_t> attrvmap_t;
- typedef std::unordered_map<std::pair<const carve::mesh::MeshSet<3>::face_t *, unsigned>, attr_t, fv_hash> attrmap_t;
+ typedef std::unordered_map<const meshset_t::vertex_t *, attr_t> attrvmap_t;
+ typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
attrmap_t attrs;
- public:
- bool hasAttribute(const carve::mesh::MeshSet<3>::face_t *f, unsigned v) {
- return attrs.find(std::make_pair(f, v)) != attrs.end();
- }
-
- attr_t getAttribute(const carve::mesh::MeshSet<3>::face_t *f, unsigned v, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator fv = attrs.find(std::make_pair(f, v));
- if (fv != attrs.end()) {
- return (*fv).second;
- }
- return def;
- }
-
- void setAttribute(const carve::mesh::MeshSet<3>::face_t *f, unsigned v, const attr_t &attr) {
- attrs[std::make_pair(f, v)] = attr;
- }
-
- virtual void interpolate(const carve::mesh::MeshSet<3>::face_t *new_face,
- const carve::mesh::MeshSet<3>::face_t *orig_face,
- bool flipped) {
+ virtual void resultFace(const carve::csg::CSG &csg,
+ const meshset_t::face_t *new_face,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
std::vector<attr_t> vertex_attrs;
attrvmap_t base_attrs;
vertex_attrs.reserve(orig_face->nVertices());
- for (carve::mesh::MeshSet<3>::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
- typename attrmap_t::const_iterator a = attrs.find(std::make_pair(orig_face, e.idx()));
+ for (meshset_t::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
+ typename attrmap_t::const_iterator a = attrs.find(key_t(orig_face, e.idx()));
if (a == attrs.end()) return;
vertex_attrs.push_back((*a).second);
base_attrs[e->vert] = vertex_attrs.back();
}
- for (carve::mesh::MeshSet<3>::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
- const carve::mesh::MeshSet<3>::vertex_t *vertex = e->vert;
+ for (meshset_t::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
+ const meshset_t::vertex_t *vertex = e->vert;
typename attrvmap_t::const_iterator b = base_attrs.find(vertex);
if (b != base_attrs.end()) {
- attrs[std::make_pair(new_face, e.idx())] = (*b).second;
+ attrs[key_t(new_face, e.idx())] = (*b).second;
} else {
carve::geom2d::P2 p = orig_face->project(e->vert->v);
attr_t attr = interp(orig_face->begin(),
@@ -266,11 +310,28 @@ namespace carve {
vertex_attrs,
p.x,
p.y);
- attrs[std::make_pair(new_face, e.idx())] = attr;
+ attrs[key_t(new_face, e.idx())] = attr;
}
}
}
+ public:
+ bool hasAttribute(const meshset_t::face_t *f, unsigned v) {
+ return attrs.find(key_t(f, v)) != attrs.end();
+ }
+
+ attr_t getAttribute(const meshset_t::face_t *f, unsigned v, const attr_t &def = attr_t()) {
+ typename attrmap_t::const_iterator fv = attrs.find(key_t(f, v));
+ if (fv != attrs.end()) {
+ return (*fv).second;
+ }
+ return def;
+ }
+
+ void setAttribute(const meshset_t::face_t *f, unsigned v, const attr_t &attr) {
+ attrs[key_t(f, v)] = attr;
+ }
+
FaceVertexAttr() : Interpolator() {
}
@@ -280,44 +341,165 @@ namespace carve {
};
+
template<typename attr_t>
- class FaceAttr : public Interpolator {
+ class FaceEdgeAttr : public Interpolator {
+ public:
+ typedef std::pair<const meshset_t::face_t *, unsigned> key_t;
protected:
- struct f_hash {
- size_t operator()(const carve::mesh::MeshSet<3>::face_t * const &f) const {
- return size_t(f);
+ typedef std::pair<const meshset_t::vertex_t *, const meshset_t::vertex_t *> vpair_t;
+
+ struct key_hash {
+ size_t operator()(const key_t &v) const {
+ return size_t(v.first) ^ size_t(v.second);
+ }
+ };
+ struct vpair_hash {
+ size_t operator()(const vpair_t &v) const {
+ return size_t(v.first) ^ size_t(v.second);
}
};
- typedef std::unordered_map<const carve::mesh::MeshSet<3>::face_t *, attr_t, f_hash> attrmap_t;
+ typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
+ typedef std::unordered_map<vpair_t, key_t, vpair_hash> edgedivmap_t;
attrmap_t attrs;
+ edgedivmap_t edgediv;
+
+ struct Hook : public Interpolator::Hook {
+ public:
+ virtual unsigned hookBits() const {
+ return
+ carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT |
+ carve::csg::CSG::Hooks::EDGE_DIVISION_BIT;
+ }
+ Hook(Interpolator *_interpolator, const carve::csg::CSG &_csg) : Interpolator::Hook(_interpolator, _csg) {
+ }
+ virtual ~Hook() {
+ }
+ };
+
+ virtual Interpolator::Hook *makeHook(carve::csg::CSG &csg) {
+ return new Hook(this, csg);
+ }
+
+ virtual void edgeDivision(const carve::csg::CSG &csg,
+ const meshset_t::edge_t *orig_edge,
+ size_t orig_edge_idx,
+ const meshset_t::vertex_t *v1,
+ const meshset_t::vertex_t *v2) {
+ key_t k(orig_edge->face, orig_edge_idx);
+ typename attrmap_t::const_iterator attr_i = attrs.find(k);
+ if (attr_i == attrs.end()) return;
+ edgediv[vpair_t(v1, v2)] = k;
+ }
+
+ virtual void processOutputFace(const carve::csg::CSG &csg,
+ std::vector<carve::mesh::MeshSet<3>::face_t *> &new_faces,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
+ edgedivmap_t undiv;
+
+ for (meshset_t::face_t::const_edge_iter_t e = orig_face->begin(); e != orig_face->end(); ++e) {
+ key_t k(orig_face, e.idx());
+ typename attrmap_t::const_iterator attr_i = attrs.find(k);
+ if (attr_i == attrs.end()) {
+ continue;
+ } else {
+ undiv[vpair_t(e->v1(), e->v2())] = k;
+ }
+ }
+
+ for (size_t fnum = 0; fnum < new_faces.size(); ++fnum) {
+ const carve::mesh::MeshSet<3>::face_t *new_face = new_faces[fnum];
+ for (meshset_t::face_t::const_edge_iter_t e = new_face->begin(); e != new_face->end(); ++e) {
+ key_t k(new_face, e.idx());
+
+ vpair_t vp;
+ if (!flipped) {
+ vp = vpair_t(e->v1(), e->v2());
+ } else {
+ vp = vpair_t(e->v2(), e->v1());
+ }
+ typename edgedivmap_t::const_iterator vp_i;
+ if ((vp_i = undiv.find(vp)) != undiv.end()) {
+ attrs[k] = attrs[vp_i->second];
+ } else if ((vp_i = edgediv.find(vp)) != edgediv.end()) {
+ attrs[k] = attrs[vp_i->second];
+ }
+ }
+ }
+ }
public:
- bool hasAttribute(const carve::mesh::MeshSet<3>::face_t *f) {
- return attrs.find(f) != attrs.end();
+
+ bool hasAttribute(const meshset_t::face_t *f, unsigned e) {
+ return attrs.find(std::make_pair(f, e)) != attrs.end();
}
- attr_t getAttribute(const carve::mesh::MeshSet<3>::face_t *f, const attr_t &def = attr_t()) {
- typename attrmap_t::const_iterator i = attrs.find(f);
- if (i != attrs.end()) {
- return (*i).second;
+ attr_t getAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &def = attr_t()) {
+ typename attrmap_t::const_iterator fv = attrs.find(std::make_pair(f, e));
+ if (fv != attrs.end()) {
+ return (*fv).second;
}
return def;
}
- void setAttribute(const carve::mesh::MeshSet<3>::face_t *f, const attr_t &attr) {
- attrs[f] = attr;
+ void setAttribute(const meshset_t::face_t *f, unsigned e, const attr_t &attr) {
+ attrs[std::make_pair(f, e)] = attr;
+ }
+
+ FaceEdgeAttr() : Interpolator() {
+ }
+
+ virtual ~FaceEdgeAttr() {
+ }
+ };
+
+
+
+ template<typename attr_t>
+ class FaceAttr : public Interpolator {
+ public:
+ typedef const meshset_t::face_t *key_t;
+
+ protected:
+ struct key_hash {
+ size_t operator()(const key_t &f) const {
+ return size_t(f);
+ }
+ };
+
+ typedef std::unordered_map<key_t, attr_t, key_hash> attrmap_t;
+
+ attrmap_t attrs;
+
+ virtual void resultFace(const carve::csg::CSG &csg,
+ const meshset_t::face_t *new_face,
+ const meshset_t::face_t *orig_face,
+ bool flipped) {
+ typename attrmap_t::const_iterator i = attrs.find(key_t(orig_face));
+ if (i != attrs.end()) {
+ attrs[key_t(new_face)] = (*i).second;
+ }
+ }
+
+ public:
+ bool hasAttribute(const meshset_t::face_t *f) {
+ return attrs.find(key_t(f)) != attrs.end();
}
- virtual void interpolate(const carve::mesh::MeshSet<3>::face_t *new_face,
- const carve::mesh::MeshSet<3>::face_t *orig_face,
- bool flipped) {
- typename attrmap_t::const_iterator i = attrs.find(orig_face);
+ attr_t getAttribute(const meshset_t::face_t *f, const attr_t &def = attr_t()) {
+ typename attrmap_t::const_iterator i = attrs.find(key_t(f));
if (i != attrs.end()) {
- attrs[new_face] = (*i).second;
+ return (*i).second;
}
+ return def;
+ }
+
+ void setAttribute(const meshset_t::face_t *f, const attr_t &attr) {
+ attrs[key_t(f)] = attr;
}
FaceAttr() : Interpolator() {
@@ -325,7 +507,6 @@ namespace carve {
virtual ~FaceAttr() {
}
-
};
}
diff --git a/extern/carve/include/carve/mesh.hpp b/extern/carve/include/carve/mesh.hpp
index 202337b64d3..115f4bf10f4 100644
--- a/extern/carve/include/carve/mesh.hpp
+++ b/extern/carve/include/carve/mesh.hpp
@@ -688,6 +688,7 @@ namespace carve {
void cacheEdges();
+ int orientationAtVertex(edge_t *);
void calcOrientation();
void recalc() {
diff --git a/extern/carve/include/carve/mesh_impl.hpp b/extern/carve/include/carve/mesh_impl.hpp
index 56fb6788b62..0748f394219 100644
--- a/extern/carve/include/carve/mesh_impl.hpp
+++ b/extern/carve/include/carve/mesh_impl.hpp
@@ -606,33 +606,78 @@ namespace carve {
template<unsigned ndim>
+ int Mesh<ndim>::orientationAtVertex(edge_t *e_base) {
+#if defined(CARVE_DEBUG)
+ std::cerr << "warning: vertex orientation not defined for ndim=" << ndim << std::endl;
+#endif
+ return 0;
+ }
+
+
+
+ template<>
+ inline int Mesh<3>::orientationAtVertex(edge_t *e_base) {
+ edge_t *e = e_base;
+ vertex_t::vector_t v_base = e->v1()->v;
+ std::vector<vertex_t::vector_t> v_edge;
+
+ if (v_edge.size() < 3) {
+ return 0;
+ }
+
+ do {
+ v_edge.push_back(e->v2()->v);
+ e = e->rev->next;
+ } while (e != e_base);
+
+ const size_t N = v_edge.size();
+
+ for (size_t i = 0; i < N; ++i) {
+ size_t j = (i + 1) % N;
+
+ double o_hi = 0.0;
+ double o_lo = 0.0;
+
+ for (size_t k = (j + 1) % N; k != i; k = (k + 1) % N) {
+ double o = carve::geom3d::orient3d(v_edge[i], v_base, v_edge[j], v_edge[k]);
+ o_hi = std::max(o_hi, o);
+ o_lo = std::max(o_lo, o);
+ }
+
+ if (o_lo >= 0.0) return +1;
+ if (o_hi <= 0.0) return -1;
+ }
+
+ return 0;
+ }
+
+
+
+ template<unsigned ndim>
void Mesh<ndim>::calcOrientation() {
if (open_edges.size() || !closed_edges.size()) {
is_negative = false;
- } else {
- edge_t *emin = closed_edges[0];
- if (emin->rev->v1()->v < emin->v1()->v) emin = emin->rev;
- for (size_t i = 1; i < closed_edges.size(); ++i) {
- if (closed_edges[i]->v1()->v < emin->v1()->v) emin = closed_edges[i];
- if (closed_edges[i]->rev->v1()->v < emin->v1()->v) emin = closed_edges[i]->rev;
- }
+ return;
+ }
- std::vector<face_t *> min_faces;
- edge_t *e = emin;
- do {
- min_faces.push_back(e->face);
- CARVE_ASSERT(e->rev != NULL);
- e = e->rev->next;
- CARVE_ASSERT(e->v1() == emin->v1());
- CARVE_ASSERT(e->v1()->v <= e->v2()->v);
- } while (e != emin);
-
- double max_abs_x = 0.0;
- for (size_t f = 0; f < min_faces.size(); ++f) {
- if (fabs(min_faces[f]->plane.N.x) > fabs(max_abs_x)) max_abs_x = min_faces[f]->plane.N.x;
- }
- is_negative = max_abs_x > 0.0;
+ edge_t *emin = closed_edges[0];
+
+ if (emin->rev->v1()->v < emin->v1()->v) emin = emin->rev;
+
+ for (size_t i = 1; i < closed_edges.size(); ++i) {
+ if (closed_edges[i]->v1()->v < emin->v1()->v) emin = closed_edges[i];
+ if (closed_edges[i]->rev->v1()->v < emin->v1()->v) emin = closed_edges[i]->rev;
+ }
+
+ int orientation = orientationAtVertex(emin);
+
+#if defined(CARVE_DEBUG)
+ if (orientation == 0) {
+ std::cerr << "warning: could not determine orientation for mesh " << this << std::endl;
}
+#endif
+
+ is_negative = orientation == -1;
}
@@ -747,7 +792,9 @@ namespace carve {
std::vector<vertex_t *> v;
size_t p = 0;
for (size_t i = 0; i < n_faces; ++i) {
- const size_t N = face_indices[p++];
+ CARVE_ASSERT(face_indices[p] > 1);
+
+ const size_t N = (size_t)face_indices[p++];
v.clear();
v.reserve(N);
for (size_t j = 0; j < N; ++j) {
diff --git a/extern/carve/include/carve/polyhedron_impl.hpp b/extern/carve/include/carve/polyhedron_impl.hpp
index de61324140d..0aadc56aefe 100644
--- a/extern/carve/include/carve/polyhedron_impl.hpp
+++ b/extern/carve/include/carve/polyhedron_impl.hpp
@@ -59,18 +59,18 @@ namespace carve {
for (size_t i = 0; i != N; ++i) {
vout.push_back(*vptr[i]);
- vmap[vertexToIndex_fast(vptr[i])] = &vout[i];
+ vmap[(size_t)vertexToIndex_fast(vptr[i])] = &vout[i];
}
for (size_t i = 0; i < faces.size(); ++i) {
face_t &f = faces[i];
for (size_t j = 0; j < f.nVertices(); ++j) {
- f.vertex(j) = vmap[vertexToIndex_fast(f.vertex(j))];
+ f.vertex(j) = vmap[(size_t)vertexToIndex_fast(f.vertex(j))];
}
}
for (size_t i = 0; i < edges.size(); ++i) {
- edges[i].v1 = vmap[vertexToIndex_fast(edges[i].v1)];
- edges[i].v2 = vmap[vertexToIndex_fast(edges[i].v2)];
+ edges[i].v1 = vmap[(size_t)vertexToIndex_fast(edges[i].v1)];
+ edges[i].v2 = vmap[(size_t)vertexToIndex_fast(edges[i].v2)];
}
vout.swap(vertices);
@@ -89,7 +89,6 @@ namespace carve {
int r = 1;
for (size_t i = 0; i < f->nEdges(); ++i) {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(f->edge(i))];
const face_t *f2 = connectedFace(f, f->edge(i));
if (f2) {
r += _faceNeighbourhood(f2, depth - 1, (*result));
@@ -114,7 +113,7 @@ namespace carve {
tagable::tag_begin();
int r = 0;
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
+ const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
for (size_t i = 0; i < edge_faces.size(); ++i) {
const face_t *f = edge_faces[i];
if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
@@ -129,7 +128,7 @@ namespace carve {
tagable::tag_begin();
int r = 0;
- const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[vertexToIndex_fast(v)];
+ const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
for (size_t i = 0; i < vertex_faces.size(); ++i) {
const face_t *f = vertex_faces[i];
if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
@@ -142,7 +141,7 @@ namespace carve {
// accessing connectivity information.
template<typename T>
int Geometry<3>::vertexToEdges(const vertex_t *v, T result) const {
- const std::vector<const edge_t *> &e = connectivity.vertex_to_edge[vertexToIndex_fast(v)];
+ const std::vector<const edge_t *> &e = connectivity.vertex_to_edge[(size_t)vertexToIndex_fast(v)];
std::copy(e.begin(), e.end(), result);
return e.size();
}
@@ -151,7 +150,7 @@ namespace carve {
template<typename T>
int Geometry<3>::vertexToFaces(const vertex_t *v, T result) const {
- const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[vertexToIndex_fast(v)];
+ const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
int c = 0;
for (size_t i = 0; i < vertex_faces.size(); ++i) {
*result++ = vertex_faces[i]; ++c;
@@ -163,7 +162,7 @@ namespace carve {
template<typename T>
int Geometry<3>::edgeToFaces(const edge_t *e, T result) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
+ const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
int c = 0;
for (size_t i = 0; i < edge_faces.size(); ++i) {
if (edge_faces[i] != NULL) { *result++ = edge_faces[i]; ++c; }
@@ -174,7 +173,7 @@ namespace carve {
inline const Geometry<3>::face_t *Geometry<3>::connectedFace(const face_t *f, const edge_t *e) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
+ const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
for (size_t i = 0; i < (edge_faces.size() & ~1U); i++) {
if (edge_faces[i] == f) return edge_faces[i^1];
}
@@ -185,7 +184,7 @@ namespace carve {
inline void Polyhedron::invert(int m_id) {
std::vector<bool> selected_manifolds(manifold_is_closed.size(), false);
- if (m_id >=0 && (unsigned)m_id < selected_manifolds.size()) selected_manifolds[m_id] = true;
+ if (m_id >=0 && (size_t)m_id < selected_manifolds.size()) selected_manifolds[(size_t)m_id] = true;
invert(selected_manifolds);
}
@@ -198,7 +197,7 @@ namespace carve {
inline bool Polyhedron::edgeOnManifold(const edge_t *e, int m_id) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
+ const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
for (size_t i = 0; i < edge_faces.size(); ++i) {
if (edge_faces[i] && edge_faces[i]->manifold_id == m_id) return true;
@@ -207,7 +206,7 @@ namespace carve {
}
inline bool Polyhedron::vertexOnManifold(const vertex_t *v, int m_id) const {
- const std::vector<const face_t *> &f = connectivity.vertex_to_face[vertexToIndex_fast(v)];
+ const std::vector<const face_t *> &f = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
for (size_t i = 0; i < f.size(); ++i) {
if (f[i]->manifold_id == m_id) return true;
@@ -219,7 +218,7 @@ namespace carve {
template<typename T>
int Polyhedron::edgeManifolds(const edge_t *e, T result) const {
- const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
+ const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[(size_t)edgeToIndex_fast(e)];
for (size_t i = 0; i < (edge_faces.size() & ~1U); i += 2) {
const face_t *f1 = edge_faces[i];
@@ -230,14 +229,14 @@ namespace carve {
else if (f2)
*result++ = f2->manifold_id;
}
- return edge_faces.size() >> 1;
+ return (int)(edge_faces.size() >> 1);
}
template<typename T>
int Polyhedron::vertexManifolds(const vertex_t *v, T result) const {
- const std::vector<const face_t *> &f = connectivity.vertex_to_face[vertexToIndex_fast(v)];
+ const std::vector<const face_t *> &f = connectivity.vertex_to_face[(size_t)vertexToIndex_fast(v)];
std::set<int> em;
for (size_t i = 0; i < f.size(); ++i) {
diff --git a/extern/carve/include/carve/polyline_decl.hpp b/extern/carve/include/carve/polyline_decl.hpp
index 5934dd25a34..0d64365610a 100644
--- a/extern/carve/include/carve/polyline_decl.hpp
+++ b/extern/carve/include/carve/polyline_decl.hpp
@@ -60,10 +60,10 @@ namespace carve {
struct PolylineEdge : public tagable {
Polyline *parent;
- unsigned edgenum;
+ size_t edgenum;
Vertex *v1, *v2;
- PolylineEdge(Polyline *_parent, int _edgenum, Vertex *_v1, Vertex *_v2);
+ PolylineEdge(Polyline *_parent, size_t _edgenum, Vertex *_v1, Vertex *_v2);
carve::geom3d::AABB aabb() const;
diff --git a/extern/carve/include/carve/polyline_impl.hpp b/extern/carve/include/carve/polyline_impl.hpp
index 3c17980a9af..067701acc65 100644
--- a/extern/carve/include/carve/polyline_impl.hpp
+++ b/extern/carve/include/carve/polyline_impl.hpp
@@ -19,7 +19,7 @@
namespace carve {
namespace line {
- inline PolylineEdge::PolylineEdge(Polyline *_parent, int _edgenum, Vertex *_v1, Vertex *_v2) :
+ inline PolylineEdge::PolylineEdge(Polyline *_parent, size_t _edgenum, Vertex *_v1, Vertex *_v2) :
tagable(), parent(_parent), edgenum(_edgenum), v1(_v1), v2(_v2) {
}
@@ -102,11 +102,11 @@ namespace carve {
PolylineEdge *e;
if (begin == end) return;
- size_t v1 = (int)*begin++;
+ size_t v1 = (size_t)*begin++;
if (begin == end) return;
while (begin != end) {
- size_t v2 = (int)*begin++;
+ size_t v2 = (size_t)*begin++;
e = new PolylineEdge(this, edges.size(), &vertices[v1], &vertices[v2]);
edges.push_back(e);
v1 = v2;
diff --git a/extern/carve/include/carve/rtree.hpp b/extern/carve/include/carve/rtree.hpp
index 65d46e5a48d..cc85b68180e 100644
--- a/extern/carve/include/carve/rtree.hpp
+++ b/extern/carve/include/carve/rtree.hpp
@@ -346,8 +346,10 @@ namespace carve {
std::vector<size_t>::iterator begin,
std::vector<size_t>::iterator end,
size_t part_size) {
+ CARVE_ASSERT(begin < end);
+
partition_info best(std::numeric_limits<double>::max(), 0);
- const size_t N = std::distance(begin, end);
+ const size_t N = (size_t)std::distance(begin, end);
std::vector<double> rhs_vol(N, 0.0);
@@ -375,7 +377,9 @@ namespace carve {
size_t part_size,
std::vector<size_t> &part_num,
size_t &part_next) {
- const size_t N = std::distance(begin, end);
+ CARVE_ASSERT(begin < end);
+
+ const size_t N = (size_t)std::distance(begin, end);
partition_info best;
partition_info curr;
@@ -406,8 +410,8 @@ namespace carve {
}
}
- for (size_t j = 0; j < best.partition_pos; ++j) part_num[begin[j]] = part_curr;
- for (size_t j = best.partition_pos; j < N; ++j) part_num[begin[j]] = part_next;
+ for (size_t j = 0; j < best.partition_pos; ++j) part_num[begin[(ssize_t)j]] = part_curr;
+ for (size_t j = best.partition_pos; j < N; ++j) part_num[begin[(ssize_t)j]] = part_next;
++part_next;
if (best.partition_pos > part_size) {
diff --git a/extern/carve/include/carve/win32.h b/extern/carve/include/carve/win32.h
index 8b5021cf2fb..5f8ce3b3bf6 100755
--- a/extern/carve/include/carve/win32.h
+++ b/extern/carve/include/carve/win32.h
@@ -37,7 +37,7 @@ typedef unsigned long uintptr_t;
#if defined(_WIN32) && !defined(__MINGW32__)
/* The __intXX are built-in types of the visual complier! So we don't
need to include anything else here.
- This typedefs should be in sync with types from BLI_sys_types.h */
+ This typedefs should be in sync with types from MEM_sys_types.h */
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
diff --git a/extern/carve/lib/geom2d.cpp b/extern/carve/lib/geom2d.cpp
index bfa84f5fd24..96527e485a5 100644
--- a/extern/carve/lib/geom2d.cpp
+++ b/extern/carve/lib/geom2d.cpp
@@ -177,12 +177,12 @@ namespace carve {
break;
}
case INTERSECTION_PP: {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + e.p2 - 2));
+ out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + (size_t)e.p2 - 2));
count++;
break;
}
case INTERSECTION_LP: {
- out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + e.p2 - 2));
+ out.push_back(PolyIntersectionInfo(INTERSECT_VERTEX, e.ipoint, i + (size_t)e.p2 - 2));
count++;
break;
}
@@ -192,7 +192,9 @@ namespace carve {
break;
}
case COLINEAR: {
- int n1 = (int)i, n2 = (int)j;
+ size_t n1 = i;
+ size_t n2 = j;
+
P2 q1 = points[i], q2 = points[j];
if (q2 < q1) { std::swap(q1, q2); std::swap(n1, n2); }
diff --git a/extern/carve/lib/intersect.cpp b/extern/carve/lib/intersect.cpp
index b468e4addc7..8e377664748 100644
--- a/extern/carve/lib/intersect.cpp
+++ b/extern/carve/lib/intersect.cpp
@@ -407,6 +407,17 @@ void carve::csg::CSG::Hooks::resultFace(const meshset_t::face_t *new_face,
}
}
+void carve::csg::CSG::Hooks::edgeDivision(const meshset_t::edge_t *orig_edge,
+ size_t orig_edge_idx,
+ const meshset_t::vertex_t *v1,
+ const meshset_t::vertex_t *v2) {
+ for (std::list<Hook *>::iterator j = hooks[EDGE_DIVISION_HOOK].begin();
+ j != hooks[EDGE_DIVISION_HOOK].end();
+ ++j) {
+ (*j)->edgeDivision(orig_edge, orig_edge_idx, v1, v2);
+ }
+}
+
void carve::csg::CSG::Hooks::registerHook(Hook *hook, unsigned hook_bits) {
for (unsigned i = 0; i < HOOK_MAX; ++i) {
if (hook_bits & (1U << i)) {
diff --git a/extern/carve/lib/intersect_face_division.cpp b/extern/carve/lib/intersect_face_division.cpp
index 75f7f790df6..0fb36c5b89d 100644
--- a/extern/carve/lib/intersect_face_division.cpp
+++ b/extern/carve/lib/intersect_face_division.cpp
@@ -719,10 +719,6 @@ namespace {
unassigned--;
}
}
-
- if (!removed.size())
- throw carve::exception("Failed to merge holes");
-
for (std::set<int>::iterator f = removed.begin(); f != removed.end(); ++f) {
for (unsigned i = 0; i < containing_faces.size(); ++i) {
containing_faces[i].erase(std::remove(containing_faces[i].begin(),
@@ -811,12 +807,14 @@ namespace {
*/
static bool assembleBaseLoop(carve::mesh::MeshSet<3>::face_t *face,
const carve::csg::detail::Data &data,
- std::vector<carve::mesh::MeshSet<3>::vertex_t *> &base_loop) {
+ std::vector<carve::mesh::MeshSet<3>::vertex_t *> &base_loop,
+ carve::csg::CSG::Hooks &hooks) {
base_loop.clear();
// XXX: assumes that face->edges is in the same order as
// face->vertices. (Which it is)
carve::mesh::MeshSet<3>::edge_t *e = face->edge;
+ size_t e_idx = 0;
bool face_edge_intersected = false;
do {
base_loop.push_back(carve::csg::map_vertex(data.vmap, e->vert));
@@ -830,9 +828,22 @@ namespace {
base_loop.push_back(ev_vec[k++]);
}
+ if (ev_vec.size() && hooks.hasHook(carve::csg::CSG::Hooks::EDGE_DIVISION_HOOK)) {
+ carve::mesh::MeshSet<3>::vertex_t *v1 = e->vert;
+ carve::mesh::MeshSet<3>::vertex_t *v2;
+ for (size_t k = 0, ke = ev_vec.size(); k < ke;) {
+ v2 = ev_vec[k++];
+ hooks.edgeDivision(e, e_idx, v1, v2);
+ v1 = v2;
+ }
+ v2 = e->v2();
+ hooks.edgeDivision(e, e_idx, v1, v2);
+ }
+
face_edge_intersected = true;
}
e = e->next;
+ ++e_idx;
} while (e != face->edge);
return face_edge_intersected;
@@ -1110,8 +1121,7 @@ namespace {
}
// copy up to the end of the path.
- if (pos < e1_1)
- std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
+ std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
CARVE_ASSERT(base_loop[e1_1] == p1.back());
std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out));
@@ -1445,7 +1455,7 @@ namespace {
std::vector<carve::mesh::MeshSet<3>::vertex_t *> base_loop;
std::list<std::vector<carve::mesh::MeshSet<3>::vertex_t *> > hole_loops;
- bool face_edge_intersected = assembleBaseLoop(face, data, base_loop);
+ bool face_edge_intersected = assembleBaseLoop(face, data, base_loop, hooks);
detail::FV2SMap::const_iterator fse_iter = data.face_split_edges.find(face);
@@ -1637,9 +1647,7 @@ namespace {
* \brief Build a set of face loops for all (split) faces of a Polyhedron.
*
* @param[in] poly The polyhedron to process
- * @param vmap
- * @param face_split_edges
- * @param divided_edges
+ * @param[in] data Internal intersection data
* @param[out] face_loops_out The resulting face loops
*
* @return The number of edges generated.
diff --git a/extern/carve/lib/triangulator.cpp b/extern/carve/lib/triangulator.cpp
index 169e5a33805..bd5a30b0c2b 100644
--- a/extern/carve/lib/triangulator.cpp
+++ b/extern/carve/lib/triangulator.cpp
@@ -27,6 +27,13 @@
#include <algorithm>
+// Support for latest Clang/LLVM on FreeBSD which does have different libcxx.
+//
+// TODO(sergey): Move it some some more generic header with platform-specific
+// declarations.
+#ifdef _LIBCPP_VERSION
+# define __is_heap is_heap
+#endif
namespace {
// private code related to hole patching.
diff --git a/extern/carve/mkfiles.sh b/extern/carve/mkfiles.sh
index d117d7531bd..bd022666418 100755
--- a/extern/carve/mkfiles.sh
+++ b/extern/carve/mkfiles.sh
@@ -1,4 +1,4 @@
#!/bin/sh
-find ./include/ -type f | sed -r 's/^\.\///' > files.txt
+find ./include/ -type f | sed -r 's/^\.\///' | grep -v /config.h > files.txt
find ./lib/ -type f | sed -r 's/^\.\///' >> files.txt
diff --git a/extern/carve/patches/clang_is_heap_fix.patch b/extern/carve/patches/clang_is_heap_fix.patch
new file mode 100644
index 00000000000..435e408d6cd
--- /dev/null
+++ b/extern/carve/patches/clang_is_heap_fix.patch
@@ -0,0 +1,17 @@
+diff -r 2e6e59022e6e lib/triangulator.cpp
+--- a/lib/triangulator.cpp Fri Nov 09 09:35:35 2012 +1100
++++ b/lib/triangulator.cpp Thu Nov 28 13:34:52 2013 +0600
+@@ -27,6 +27,13 @@
+
+ #include <algorithm>
+
++// Support for latest Clang/LLVM on FreeBSD which does have different libcxx.
++//
++// TODO(sergey): Move it some some more generic header with platform-specific
++// declarations.
++#ifdef _LIBCPP_VERSION
++# define __is_heap is_heap
++#endif
+
+ namespace {
+ // private code related to hole patching.
diff --git a/extern/carve/patches/files/random.hpp b/extern/carve/patches/files/random.hpp
deleted file mode 100644
index 15866bb496e..00000000000
--- a/extern/carve/patches/files/random.hpp
+++ /dev/null
@@ -1,773 +0,0 @@
-#pragma once
-
-#include <iostream>
-#include <vector>
-#include <limits>
-#include <stdexcept>
-#include <cmath>
-#include <algorithm>
-
-#if !defined(_MSC_VER)
-#include <stdint.h>
-#endif
-
-namespace boost {
-
-// type_traits could help here, but I don't want to depend on type_traits.
-template<class T>
-struct ptr_helper
-{
- typedef T value_type;
- typedef T& reference_type;
- typedef const T& rvalue_type;
- static reference_type ref(T& r) { return r; }
- static const T& ref(const T& r) { return r; }
-};
-
-template<class T>
-struct ptr_helper<T&>
-{
- typedef T value_type;
- typedef T& reference_type;
- typedef T& rvalue_type;
- static reference_type ref(T& r) { return r; }
- static const T& ref(const T& r) { return r; }
-};
-
-template<class T>
-struct ptr_helper<T*>
-{
- typedef T value_type;
- typedef T& reference_type;
- typedef T* rvalue_type;
- static reference_type ref(T * p) { return *p; }
- static const T& ref(const T * p) { return *p; }
-};
-
-template<class UniformRandomNumberGenerator>
-class pass_through_engine
-{
-private:
- typedef ptr_helper<UniformRandomNumberGenerator> helper_type;
-
-public:
- typedef typename helper_type::value_type base_type;
- typedef typename base_type::result_type result_type;
-
- explicit pass_through_engine(UniformRandomNumberGenerator rng)
- // make argument an rvalue to avoid matching Generator& constructor
- : _rng(static_cast<typename helper_type::rvalue_type>(rng))
- { }
-
- result_type min () const { return (base().min)(); }
- result_type max () const { return (base().max)(); }
- base_type& base() { return helper_type::ref(_rng); }
- const base_type& base() const { return helper_type::ref(_rng); }
-
- result_type operator()() { return base()(); }
-
-private:
- UniformRandomNumberGenerator _rng;
-};
-
-template<class RealType>
-class new_uniform_01
-{
-public:
- typedef RealType input_type;
- typedef RealType result_type;
- // compiler-generated copy ctor and copy assignment are fine
- result_type min () const { return result_type(0); }
- result_type max () const { return result_type(1); }
- void reset() { }
-
- template<class Engine>
- result_type operator()(Engine& eng) {
- for (;;) {
- typedef typename Engine::result_type base_result;
- result_type factor = result_type(1) /
- (result_type((eng.max)()-(eng.min)()) +
- result_type(std::numeric_limits<base_result>::is_integer ? 1 : 0));
- result_type result = result_type(eng() - (eng.min)()) * factor;
- if (result < result_type(1))
- return result;
- }
- }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const new_uniform_01&)
- {
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, new_uniform_01&)
- {
- return is;
- }
-};
-
-template<class UniformRandomNumberGenerator, class RealType>
-class backward_compatible_uniform_01
-{
- typedef ptr_helper<UniformRandomNumberGenerator> traits;
- typedef pass_through_engine<UniformRandomNumberGenerator> internal_engine_type;
-public:
- typedef UniformRandomNumberGenerator base_type;
- typedef RealType result_type;
-
- static const bool has_fixed_range = false;
-
- explicit backward_compatible_uniform_01(typename traits::rvalue_type rng)
- : _rng(rng),
- _factor(result_type(1) /
- (result_type((_rng.max)()-(_rng.min)()) +
- result_type(std::numeric_limits<base_result>::is_integer ? 1 : 0)))
- {
- }
- // compiler-generated copy ctor and copy assignment are fine
-
- result_type min () const { return result_type(0); }
- result_type max () const { return result_type(1); }
- typename traits::value_type& base() { return _rng.base(); }
- const typename traits::value_type& base() const { return _rng.base(); }
- void reset() { }
-
- result_type operator()() {
- for (;;) {
- result_type result = result_type(_rng() - (_rng.min)()) * _factor;
- if (result < result_type(1))
- return result;
- }
- }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const backward_compatible_uniform_01& u)
- {
- os << u._rng;
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, backward_compatible_uniform_01& u)
- {
- is >> u._rng;
- return is;
- }
-
-private:
- typedef typename internal_engine_type::result_type base_result;
- internal_engine_type _rng;
- result_type _factor;
-};
-
-// A definition is required even for integral static constants
-template<class UniformRandomNumberGenerator, class RealType>
-const bool backward_compatible_uniform_01<UniformRandomNumberGenerator, RealType>::has_fixed_range;
-
-template<class UniformRandomNumberGenerator>
-struct select_uniform_01
-{
- template<class RealType>
- struct apply
- {
- typedef backward_compatible_uniform_01<UniformRandomNumberGenerator, RealType> type;
- };
-};
-
-template<>
-struct select_uniform_01<float>
-{
- template<class RealType>
- struct apply
- {
- typedef new_uniform_01<float> type;
- };
-};
-
-template<>
-struct select_uniform_01<double>
-{
- template<class RealType>
- struct apply
- {
- typedef new_uniform_01<double> type;
- };
-};
-
-template<>
-struct select_uniform_01<long double>
-{
- template<class RealType>
- struct apply
- {
- typedef new_uniform_01<long double> type;
- };
-};
-
-// Because it is so commonly used: uniform distribution on the real [0..1)
-// range. This allows for specializations to avoid a costly int -> float
-// conversion plus float multiplication
-template<class UniformRandomNumberGenerator = double, class RealType = double>
-class uniform_01
- : public select_uniform_01<UniformRandomNumberGenerator>::template apply<RealType>::type
-{
- typedef typename select_uniform_01<UniformRandomNumberGenerator>::template apply<RealType>::type impl_type;
- typedef ptr_helper<UniformRandomNumberGenerator> traits;
-public:
-
- uniform_01() {}
-
- explicit uniform_01(typename traits::rvalue_type rng)
- : impl_type(rng)
- {
- }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_01& u)
- {
- os << static_cast<const impl_type&>(u);
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, uniform_01& u)
- {
- is >> static_cast<impl_type&>(u);
- return is;
- }
-};
-
-template<class UniformRandomNumberGenerator, class IntType = unsigned long>
-class uniform_int_float
-{
-public:
- typedef UniformRandomNumberGenerator base_type;
- typedef IntType result_type;
-
- uniform_int_float(base_type rng, IntType min_arg = 0, IntType max_arg = 0xffffffff)
- : _rng(rng), _min(min_arg), _max(max_arg)
- {
- init();
- }
-
- result_type min () const { return _min; }
- result_type max () const { return _max; }
- base_type& base() { return _rng.base(); }
- const base_type& base() const { return _rng.base(); }
-
- result_type operator()()
- {
- return static_cast<IntType>(_rng() * _range) + _min;
- }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_int_float& ud)
- {
- os << ud._min << " " << ud._max;
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, uniform_int_float& ud)
- {
- is >> std::ws >> ud._min >> std::ws >> ud._max;
- ud.init();
- return is;
- }
-
-private:
- void init()
- {
- _range = static_cast<base_result>(_max-_min)+1;
- }
-
- typedef typename base_type::result_type base_result;
- uniform_01<base_type> _rng;
- result_type _min, _max;
- base_result _range;
-};
-
-
-template<class UniformRandomNumberGenerator, class CharT, class Traits>
-std::basic_ostream<CharT,Traits>&
-operator<<(
- std::basic_ostream<CharT,Traits>& os
- , const pass_through_engine<UniformRandomNumberGenerator>& ud
- )
-{
- return os << ud.base();
-}
-
-template<class UniformRandomNumberGenerator, class CharT, class Traits>
-std::basic_istream<CharT,Traits>&
-operator>>(
- std::basic_istream<CharT,Traits>& is
- , const pass_through_engine<UniformRandomNumberGenerator>& ud
- )
-{
- return is >> ud.base();
-}
-
-
-
-template<class RealType = double>
-class normal_distribution
-{
-public:
- typedef RealType input_type;
- typedef RealType result_type;
-
- explicit normal_distribution(const result_type& mean_arg = result_type(0),
- const result_type& sigma_arg = result_type(1))
- : _mean(mean_arg), _sigma(sigma_arg), _valid(false)
- {
- //assert(_sigma >= result_type(0));
- }
-
- // compiler-generated copy constructor is NOT fine, need to purge cache
- normal_distribution(const normal_distribution& other)
- : _mean(other._mean), _sigma(other._sigma), _valid(false)
- {
- }
-
- // compiler-generated copy ctor and assignment operator are fine
-
- RealType mean() const { return _mean; }
- RealType sigma() const { return _sigma; }
-
- void reset() { _valid = false; }
-
- template<class Engine>
- result_type operator()(Engine& eng)
- {
-#ifndef BOOST_NO_STDC_NAMESPACE
- // allow for Koenig lookup
- using std::sqrt; using std::log; using std::sin; using std::cos;
-#endif
- if(!_valid) {
- _r1 = eng();
- _r2 = eng();
- _cached_rho = sqrt(-result_type(2) * log(result_type(1)-_r2));
- _valid = true;
- } else {
- _valid = false;
- }
- // Can we have a boost::mathconst please?
- const result_type pi = result_type(3.14159265358979323846);
-
- return _cached_rho * (_valid ?
- cos(result_type(2)*pi*_r1) :
- sin(result_type(2)*pi*_r1))
- * _sigma + _mean;
- }
-
-#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const normal_distribution& nd)
- {
- os << nd._mean << " " << nd._sigma << " "
- << nd._valid << " " << nd._cached_rho << " " << nd._r1;
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, normal_distribution& nd)
- {
- is >> std::ws >> nd._mean >> std::ws >> nd._sigma
- >> std::ws >> nd._valid >> std::ws >> nd._cached_rho
- >> std::ws >> nd._r1;
- return is;
- }
-#endif
-private:
- result_type _mean, _sigma;
- result_type _r1, _r2, _cached_rho;
- bool _valid;
-};
-
-// http://www.math.keio.ac.jp/matumoto/emt.html
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-class mersenne_twister
-{
-public:
- typedef UIntType result_type;
- static const int word_size = w;
- static const int state_size = n;
- static const int shift_size = m;
- static const int mask_bits = r;
- static const UIntType parameter_a = a;
- static const int output_u = u;
- static const int output_s = s;
- static const UIntType output_b = b;
- static const int output_t = t;
- static const UIntType output_c = c;
- static const int output_l = l;
-
- static const bool has_fixed_range = false;
-
- mersenne_twister() { seed(); }
-
- explicit mersenne_twister(const UIntType& value)
- { seed(value); }
- template<class It> mersenne_twister(It& first, It last) { seed(first,last); }
-
- template<class Generator> \
- explicit mersenne_twister(Generator& gen)
- { seed(gen); }
-
- // compiler-generated copy ctor and assignment operator are fine
-
- void seed() { seed(UIntType(5489)); }
-
- void seed(const UIntType& value)
- {
- // New seeding algorithm from
- // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
- // In the previous versions, MSBs of the seed affected only MSBs of the
- // state x[].
- const UIntType mask = ~0u;
- x[0] = value & mask;
- for (i = 1; i < n; i++) {
- // See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106
- x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
- }
- }
-
- // For GCC, moving this function out-of-line prevents inlining, which may
- // reduce overall object code size. However, MSVC does not grok
- // out-of-line definitions of member function templates.
- template<class Generator> \
- void seed(Generator& gen)
- {
-/*#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
- BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_signed);
-#endif*/
- // I could have used std::generate_n, but it takes "gen" by value
- for(int j = 0; j < n; j++)
- x[j] = gen();
- i = n;
- }
-
- template<class It>
- void seed(It& first, It last)
- {
- int j;
- for(j = 0; j < n && first != last; ++j, ++first)
- x[j] = *first;
- i = n;
- if(first == last && j < n)
- throw std::invalid_argument("mersenne_twister::seed");
- }
-
- result_type min () const { return 0; }
- result_type max () const
- {
- // avoid "left shift count >= with of type" warning
- result_type res = 0;
- for(int j = 0; j < w; ++j)
- res |= (1u << j);
- return res;
- }
-
- result_type operator()();
- static bool validation(result_type v) { return val == v; }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const mersenne_twister& mt)
- {
- for(int j = 0; j < mt.state_size; ++j)
- os << mt.compute(j) << " ";
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, mersenne_twister& mt)
- {
- for(int j = 0; j < mt.state_size; ++j)
- is >> mt.x[j] >> std::ws;
- // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template
- // value parameter "n" available from the class template scope, so use
- // the static constant with the same value
- mt.i = mt.state_size;
- return is;
- }
-
- friend bool operator==(const mersenne_twister& x, const mersenne_twister& y)
- {
- for(int j = 0; j < state_size; ++j)
- if(x.compute(j) != y.compute(j))
- return false;
- return true;
- }
-
- friend bool operator!=(const mersenne_twister& x, const mersenne_twister& y)
- { return !(x == y); }
-
-private:
- // returns x(i-n+index), where index is in 0..n-1
- UIntType compute(unsigned int index) const
- {
- // equivalent to (i-n+index) % 2n, but doesn't produce negative numbers
- return x[ (i + n + index) % (2*n) ];
- }
- void twist(int block);
-
- // state representation: next output is o(x(i))
- // x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents
- // x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)]
- // The goal is to always have x(i-n) ... x(i-1) available for
- // operator== and save/restore.
-
- UIntType x[2*n];
- int i;
-};
-
-// A definition is required even for integral static constants
-
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const bool mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::has_fixed_range;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::state_size;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::shift_size;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::mask_bits;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::parameter_a;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_u;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_s;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_b;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_t;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_c;
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_l;
-
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-void mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::twist(int block)
-{
- const UIntType upper_mask = (~0u) << r;
- const UIntType lower_mask = ~upper_mask;
-
- if(block == 0) {
- for(int j = n; j < 2*n; j++) {
- UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask);
- x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
- }
- } else if (block == 1) {
- // split loop to avoid costly modulo operations
- { // extra scope for MSVC brokenness w.r.t. for scope
- for(int j = 0; j < n-m; j++) {
- UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
- x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0);
- }
- }
-
- for(int j = n-m; j < n-1; j++) {
- UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
- x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
- }
- // last iteration
- UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask);
- x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0);
- i = 0;
- }
-}
-
-template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l, UIntType val>
-inline typename mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::result_type
-mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::operator()()
-{
- if(i == n)
- twist(0);
- else if(i >= 2*n)
- twist(1);
- // Step 4
- UIntType z = x[i];
- ++i;
- z ^= (z >> u);
- z ^= ((z << s) & b);
- z ^= ((z << t) & c);
- z ^= (z >> l);
- return z;
-}
-
-typedef mersenne_twister<uint32_t,32,351,175,19,0xccab8ee7,11,
- 7,0x31b6ab00,15,0xffe50000,17, 0xa37d3c92> mt11213b;
-
-// validation by experiment from mt19937.c
-typedef mersenne_twister<uint32_t,32,624,397,31,0x9908b0df,11,
- 7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
-
-
-template<class RealType = double, class Cont = std::vector<RealType> >
-class uniform_on_sphere
-{
-public:
- typedef RealType input_type;
- typedef Cont result_type;
-
- explicit uniform_on_sphere(int dim = 2) : _container(dim), _dim(dim) { }
-
- // compiler-generated copy ctor and assignment operator are fine
-
- void reset() { _normal.reset(); }
-
- template<class Engine>
- const result_type & operator()(Engine& eng)
- {
- RealType sqsum = 0;
- for(typename Cont::iterator it = _container.begin();
- it != _container.end();
- ++it) {
- RealType val = _normal(eng);
- *it = val;
- sqsum += val * val;
- }
- using std::sqrt;
- // for all i: result[i] /= sqrt(sqsum)
- std::transform(_container.begin(), _container.end(), _container.begin(),
- std::bind2nd(std::divides<RealType>(), sqrt(sqsum)));
- return _container;
- }
-
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_on_sphere& sd)
- {
- os << sd._dim;
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, uniform_on_sphere& sd)
- {
- is >> std::ws >> sd._dim;
- sd._container.resize(sd._dim);
- return is;
- }
-
-private:
- normal_distribution<RealType> _normal;
- result_type _container;
- int _dim;
-};
-
-
-
-template<bool have_int, bool want_int>
-struct engine_helper;
-
-
-template<>
-struct engine_helper<true, true>
-{
- template<class Engine, class DistInputType>
- struct impl
- {
- typedef pass_through_engine<Engine> type;
- };
-};
-
-template<>
-struct engine_helper<false, false>
-{
- template<class Engine, class DistInputType>
- struct impl
- {
- typedef uniform_01<Engine, DistInputType> type;
- };
-};
-
-template<>
-struct engine_helper<true, false>
-{
- template<class Engine, class DistInputType>
- struct impl
- {
- typedef uniform_01<Engine, DistInputType> type;
- };
-};
-
-template<>
-struct engine_helper<false, true>
-{
- template<class Engine, class DistInputType>
- struct impl
- {
- typedef uniform_int_float<Engine, unsigned long> type;
- };
-};
-
-template<class Engine, class Distribution>
-class variate_generator
-{
-private:
- typedef pass_through_engine<Engine> decorated_engine;
-
-public:
- typedef typename decorated_engine::base_type engine_value_type;
- typedef Engine engine_type;
- typedef Distribution distribution_type;
- typedef typename Distribution::result_type result_type;
-
- variate_generator(Engine e, Distribution d)
- : _eng(decorated_engine(e)), _dist(d) { }
-
- result_type operator()() { return _dist(_eng); }
- template<class T>
- result_type operator()(T value) { return _dist(_eng, value); }
-
- engine_value_type& engine() { return _eng.base().base(); }
- const engine_value_type& engine() const { return _eng.base().base(); }
-
- distribution_type& distribution() { return _dist; }
- const distribution_type& distribution() const { return _dist; }
-
- result_type min () const { return (distribution().min)(); }
- result_type max () const { return (distribution().max)(); }
-
-private:
- enum {
- have_int = std::numeric_limits<typename decorated_engine::result_type>::is_integer,
- want_int = std::numeric_limits<typename Distribution::input_type>::is_integer
- };
- typedef typename engine_helper<have_int, want_int>::template impl<decorated_engine, typename Distribution::input_type>::type internal_engine_type;
-
- internal_engine_type _eng;
- distribution_type _dist;
-};
-
-} // namespace boost
diff --git a/extern/carve/patches/series b/extern/carve/patches/series
index 0b1f731805e..5b72b49c8ca 100644
--- a/extern/carve/patches/series
+++ b/extern/carve/patches/series
@@ -3,3 +3,4 @@ win32.patch
mesh_iterator.patch
mingw.patch
gcc46.patch
+clang_is_heap_fix.patch
diff --git a/extern/libmv/libmv/numeric/numeric.h b/extern/libmv/libmv/numeric/numeric.h
index a95723d59cf..81705c4b370 100644
--- a/extern/libmv/libmv/numeric/numeric.h
+++ b/extern/libmv/libmv/numeric/numeric.h
@@ -44,9 +44,11 @@
inline long lround(double d) {
return (long)(d>0 ? d+0.5 : ceil(d-0.5));
}
+#if _MSC_VER < 1800
inline int round(double d) {
return (d>0) ? int(d+0.5) : int(d-0.5);
}
+#endif
typedef unsigned int uint;
#endif // _WIN32
diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt
index 56fd4c25473..52e2246b13f 100644
--- a/extern/libmv/third_party/ceres/CMakeLists.txt
+++ b/extern/libmv/third_party/ceres/CMakeLists.txt
@@ -46,6 +46,7 @@ set(SRC
internal/ceres/block_jacobi_preconditioner.cc
internal/ceres/block_random_access_crs_matrix.cc
internal/ceres/block_random_access_dense_matrix.cc
+ internal/ceres/block_random_access_diagonal_matrix.cc
internal/ceres/block_random_access_matrix.cc
internal/ceres/block_random_access_sparse_matrix.cc
internal/ceres/block_sparse_matrix.cc
@@ -70,6 +71,7 @@ set(SRC
internal/ceres/dogleg_strategy.cc
internal/ceres/evaluator.cc
internal/ceres/file.cc
+ internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/implicit_schur_complement.cc
@@ -97,11 +99,11 @@ set(SRC
internal/ceres/program.cc
internal/ceres/residual_block.cc
internal/ceres/residual_block_utils.cc
- internal/ceres/runtime_numeric_diff_cost_function.cc
internal/ceres/schur_complement_solver.cc
internal/ceres/schur_eliminator.cc
internal/ceres/schur_jacobi_preconditioner.cc
internal/ceres/scratch_evaluate_preparer.cc
+ internal/ceres/single_linkage_clustering.cc
internal/ceres/solver.cc
internal/ceres/solver_impl.cc
internal/ceres/sparse_matrix.cc
@@ -127,6 +129,7 @@ set(SRC
include/ceres/covariance.h
include/ceres/crs_matrix.h
include/ceres/dynamic_autodiff_cost_function.h
+ include/ceres/dynamic_numeric_diff_cost_function.h
include/ceres/fpclassify.h
include/ceres/gradient_checker.h
include/ceres/internal/autodiff.h
@@ -158,6 +161,7 @@ set(SRC
internal/ceres/block_jacobi_preconditioner.h
internal/ceres/block_random_access_crs_matrix.h
internal/ceres/block_random_access_dense_matrix.h
+ internal/ceres/block_random_access_diagonal_matrix.h
internal/ceres/block_random_access_matrix.h
internal/ceres/block_random_access_sparse_matrix.h
internal/ceres/block_sparse_matrix.h
@@ -206,6 +210,7 @@ set(SRC
internal/ceres/parameter_block.h
internal/ceres/parameter_block_ordering.h
internal/ceres/partitioned_matrix_view.h
+ internal/ceres/partitioned_matrix_view_impl.h
internal/ceres/polynomial.h
internal/ceres/preconditioner.h
internal/ceres/problem_impl.h
@@ -214,12 +219,12 @@ set(SRC
internal/ceres/random.h
internal/ceres/residual_block.h
internal/ceres/residual_block_utils.h
- internal/ceres/runtime_numeric_diff_cost_function.h
internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.h
internal/ceres/schur_eliminator_impl.h
internal/ceres/schur_jacobi_preconditioner.h
internal/ceres/scratch_evaluate_preparer.h
+ internal/ceres/single_linkage_clustering.h
internal/ceres/small_blas.h
internal/ceres/solver_impl.h
internal/ceres/sparse_matrix.h
@@ -238,6 +243,22 @@ set(SRC
#if(FALSE)
# list(APPEND SRC
+# internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
+# internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
+# internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
+# internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
+# internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
+# internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
+# internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
+# internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
+# internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
+# internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
+# internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
+# internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
+# internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
+# internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
+# internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
+# internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
# internal/ceres/generated/schur_eliminator_2_2_2.cc
# internal/ceres/generated/schur_eliminator_2_2_3.cc
# internal/ceres/generated/schur_eliminator_2_2_4.cc
@@ -249,6 +270,7 @@ set(SRC
# internal/ceres/generated/schur_eliminator_2_4_3.cc
# internal/ceres/generated/schur_eliminator_2_4_4.cc
# internal/ceres/generated/schur_eliminator_2_4_d.cc
+# internal/ceres/generated/schur_eliminator_2_d_d.cc
# internal/ceres/generated/schur_eliminator_4_4_2.cc
# internal/ceres/generated/schur_eliminator_4_4_3.cc
# internal/ceres/generated/schur_eliminator_4_4_4.cc
@@ -287,23 +309,54 @@ if(WITH_OPENMP)
)
endif()
-if(MSVC10)
- add_definitions(
- -D"CERES_HASH_NAMESPACE_START=namespace std {"
- -D"CERES_HASH_NAMESPACE_END=}"
- )
-else()
- add_definitions(
- -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
- -D"CERES_HASH_NAMESPACE_END=}}"
- )
-endif()
+include(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER)
+if(HAVE_STD_UNORDERED_MAP_HEADER)
+ # Even so we've found unordered_map header file it doesn't
+ # mean unordered_map and unordered_set will be declared in
+ # std namespace.
+ #
+ # Namely, MSVC 2008 have unordered_map header which declares
+ # unordered_map class in std::tr1 namespace. In order to support
+ # this, we do extra check to see which exactly namespace is
+ # to be used.
-if(APPLE)
- if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5")
- add_definitions(
- -DCERES_NO_TR1
- )
+ include(CheckCXXSourceCompiles)
+ CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+ int main() {
+ std::unordered_map<int, int> map;
+ return 0;
+ }"
+ HAVE_UNURDERED_MAP_IN_STD_NAMESPACE)
+ if(HAVE_UNURDERED_MAP_IN_STD_NAMESPACE)
+ add_definitions(-DCERES_STD_UNORDERED_MAP)
+ message(STATUS "Found unordered_map/set in std namespace.")
+ else()
+ CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+ int main() {
+ std::tr1::unordered_map<int, int> map;
+ return 0;
+ }"
+ HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE)
+ if(HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ message(STATUS "Found unordered_map/set in std::tr1 namespace.")
+ else()
+ message(STATUS "Found <unordered_map> but cannot find either std::unordered_map "
+ "or std::tr1::unordered_map.")
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ add_definitions(-DCERES_NO_UNORDERED_MAP)
+ endif()
+ endif()
+else()
+ CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" UNORDERED_MAP_IN_TR1_NAMESPACE)
+ if(UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCERES_TR1_UNORDERED_MAP)
+ message(STATUS "Found unordered_map/set in std::tr1 namespace.")
+ else()
+ message(STATUS "Unable to find <unordered_map> or <tr1/unordered_map>. ")
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ add_definitions(-DCERES_NO_UNORDERED_MAP)
endif()
endif()
diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog
index 6bb33068b2a..2bd4206cf47 100644
--- a/extern/libmv/third_party/ceres/ChangeLog
+++ b/extern/libmv/third_party/ceres/ChangeLog
@@ -1,638 +1,684 @@
-commit 682cd3c27864ba6d67ca81890760a5f697f21d63
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue Sep 3 14:28:32 2013 -0700
-
- Update version history with shared libs changes
-
- Change-Id: Iafd55087bc5eef4c15c3b544222147aa99df7690
-
-commit 340d7c1415f144ca335ec1e87832c3f41d5d515b
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue Sep 3 13:50:03 2013 -0700
-
- Update version history with miniglog fix
-
- Change-Id: Ic69f4994259e05fa88548b957146a1aac73b7af7
-
-commit ac061c0f2334868e671f26d24e34a14c77fac716
-Author: Keir Mierle <mierle@gmail.com>
-Date: Tue Sep 3 13:03:28 2013 -0700
+commit 33e01b9c5e1416fe29c55ac0332cdca21c053c83
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Nov 27 10:24:03 2013 -0800
- Cleanups in logging.h
+ Rename LinearSolverTerminationType enums.
- Thanks to Scott Ettinger for the patch this is based off of,
- which restores the NDK build.
+ This increases clarity, drops redundant enums and makes things
+ cleaner all around.
- Change-Id: I8036dc1388438a4940e6f4ae297162902afd8d3a
+ Change-Id: I761f195ddf17ea6bd8e4e55bf5a72863660c4c3b
-commit 0338f9a8e69582a550ef6d128e447779536d623c
+commit 068437eb89d495d905465544ccd442efef457b04
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Sep 2 22:28:40 2013 -0700
+Date: Wed Nov 27 07:05:57 2013 -0800
- ITERATIVE_SCHUR works with no f-blocks.
-
- When the Schur complement is of size zero,
- i.e. none of the parameter blocks interact
- with each other, the ITERATIVE_SCHUR linear
- solver crashes due to some checks that are
- triggered in the SCHUR_JACOBI preconditioner.
+ Pipe minimizer termination messages to Solver::Summary.
- This patch adds logic to detect this condition
- and to deal with it and adds tests that verify
- the fix.
+ All minimizer termination messages are now available as
+ Solver::Summary::error.
- Thanks to Soohyun Bae for reporting this bug.
+ This is part of the ongoing refactoring or
- Change-Id: If29ddf32463cbb1960414fff0e29bbf0d2ee7989
+ Change-Id: I4514c3c042645bbd1471bcde9bd3dbf81d9ee8b0
-commit 263de47419167786c9ab6d93fa2f3e32e8e75fe1
-Author: Taylor Braun-Jones <taylor@braun-jones.org>
-Date: Thu Aug 29 10:33:29 2013 -0400
+commit 89a592f410fb6f80c03dea84b6b9f1a10bea36c1
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Nov 26 11:35:49 2013 -0800
- Incorporate RHEL build fixes from Brian Pitts
+ LinearSolver::Summary::status -> LinearSolver::Summary::message.
- CMake build fixed so that versioned shared libraries are installed
- (along with .so symlinks)
+ And a bunch of minor lint cleanups as they showed up.
- Change-Id: Ibbaea9d37d17754cb8c3cd36fc17d015ca7d2a57
+ Change-Id: I430a6b05710923c72daf6a5df4dfcd16fbf44b3a
-commit 6b4131993ec0db6c850bb2ae07ba8793dbab3e39
+commit b16e118b96c55451c0d8556f3c5b52ad36b69cac
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 26 00:02:50 2013 -0700
+Date: Mon Nov 25 05:47:43 2013 -0800
- Update spec file
+ Better error checking and reporting for linear solvers.
- Change-Id: Id6426d7cad41cde2cbab411964ac013d724a066c
-
-commit c24a4ec6fb6202d1f6a576f211b99fbe9c9906ef
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 23 06:49:22 2013 -0700
-
- Cmake refactoring
+ A lot of error checking cruft has accumulated over the years
+ in the various linear solvers. This change makes the error reporting
+ more robust and consistent across the various solvers.
- 1. Use CMake FindLAPACK and FindBLAS Modules.
- 2. Remove SEARCH_HEADERS and SEARCH_LIBS and replace them with
- CMAKE variables. This leads to simplification of the FIND_LIBRARY
- and FIND_PATH calls.
- 3. Make miniglog a fallback when glog is not present and the
- user indicates MINIGLOG=OFF.
- 4. Add time.h to miniglog.
- 5. Remove shared library building.
+ Preconditioners are not covered by this change and will be the
+ subject of a future change.
- Change-Id: I8a97156d3d7cf645fbbfe8e571761bc16c89f43f
+ Change-Id: Ibeb2572a1e67758953dde8d12e3abc6d1df9052d
-commit 48e9cd31db0bf7223beb83cdc90e3cd2b5aad054
+commit 5794d41be2d8d6a67dcdfe607e66050f0ac04c55
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 21 10:55:16 2013 -0700
+Date: Mon Nov 25 13:37:02 2013 -0800
- Add a test name
+ Remove overzealous checks in Summary::FullReport.
+
+ Thanks to sebi.koch@gmail.com for reporting this.
- Change-Id: I06dfc9cad2c54ef6078342766577eab92645283f
+ Change-Id: I1ba9b375e5cf66639e292ba37b34a90446f13162
-commit 126dfbe27df9c5b9f41cf7cc92b75c1219518283
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 20 22:34:34 2013 -0700
+commit 40ef90304ac200bb948549e8e3748e487d27dc53
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Mon Nov 25 16:36:40 2013 +0000
- Fix how Ceres calls CAMD.
+ Adding VLOG output to line search.
- CAMD requires that the id of the largest numbered elimination
- group be less than the number of columns in the matrix.
+ - Previously line search was sparse in terms of debug orientated VLOG
+ output which made debugging failure cases difficult.
- This patch ensures that this is the case. Without this,
- in certain cases its possible for CAMD to silently fail
- while doing out of bounds access and then causing Ceres to fail.
-
- Also add some logging about the problem size before and after
- the reduced program has been created.
-
- Change-Id: I0ea3c6572a7c29cbbf09afec9ba5b4f4d4b21a9b
+ Change-Id: Idfabf74d2b3f7b8256f79dff8c6b7fcdc2fcf4d3
-commit 69af5d8b4d7c48b2efa3c61e51c86cfa1b380b8a
+commit 1284a5141426597f3ca1e29ae8548c9b4c43c9c1
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 20 13:58:59 2013 -0700
+Date: Sun Nov 24 15:09:43 2013 -0800
- Add comments to trust_region_minimizer.cc.
+ Use explicit formula to solve quadratic polynomials.
+
+ polynomial.cc implements a companion matrix base method for solving
+ polynomials. This is both expensive and numerically sensitive.
- trust_region_minimizer.cc now contains a comment that explains
- the reasoning behind he inner iteration step acceptance change.
+ This change adds a quadratic equation solver. Instead of using the
+ usual quadratic formula, it uses the formula suggested by BKP Horn
+ for improved numerical stability.
- Change-Id: I4eaa69d6bab92c543bba3f119c09f44625d393bd
+ Change-Id: I476933ce010d81db992f1c580d2fb23a4457eb3e
-commit e45db9d05aaa26b1ddffa44c9190a1018aa2655f
+commit a9334d67d7973c0f56e65f12ae897dd53504ef0d
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 19 23:13:29 2013 -0700
+Date: Wed Nov 20 10:12:23 2013 -0800
- Improve inner iteration step acceptance.
-
- Normally, in a trust region algorithm the quality of a trust region step
- is measured by the ratio
-
- nonlinear_cost_change
- r = ---------------------
- model_cost_change
-
- All the change in the nonlinear objective is due to the trust region step
- so this ratio is a good measure of the quality of the trust region radius.
-
- However, when inner iterations are being used, nonlinear_cost_change
- includes the contribution of the inner iterations and its not fair to
- credit it all to the trust region algorithm. So we change the ratio to be
-
- nonlinear_cost_change
- r = ------------------------------------------------
- (model_cost_change + inner_iteration_cost_change)
-
- In most cases this is fine, but it can be the case that the
- change in solution quality due to inner iterations is so large
- and the trust region step is so bad, that this ratio can become
- quite small.
+ Fix constant parameter handling in inner iterations.
- This can cause the trust region loop to reject this step.
+ There was a bug in the way RemoveFixedBlocksFromProgram was working.
+ It only removed the constant parameter blocks from the
+ linear_solver_ordering, it was not even aware of the
+ inner_iteration_ordering.
- This change, fixes this problem by looking at the inner_iteration_cost_change
- explicitly and accepting a step if the inner iterations led to a net
- decrease in the objective function value.
+ This change fixes this bug. The code for RemoveFixedBlocksFromProgram
+ is also cleaned up and made more readable and the test have been updated.
- Along the way it also fixes the way model_cost_change is computed.
- Changing to a more numerically robust way of computing it.
+ Thanks to Mikael Persson for reporting this.
- The last and final change is to ensure that inner iterations and the
- non-monotonic version of the trust region algorithm interact correctly.
-
- This addresses part 2 of
-
- https://code.google.com/p/ceres-solver/issues/detail?id=115
-
- As an illustration of the change.
-
- Before this change
+ Change-Id: I454fa89f9b6f4f6320b02d5235e6f322cc15ff51
+
+commit 331ff090dcae7096cea50144047b71cab2d3e819
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Mon Nov 25 13:44:53 2013 +0000
+
+ Downgrading log status of BFGS secant condition messages.
- [master] build: ./bin/bundle_adjuster --input ~/Downloads/problem-245-198739-pre.txt -num_iterations 10 -translation_sigma 0.01 -rotation_sigma 0.001 -point_sigma 0.1 -inner_iterations -num_threads 4
- 0: f: 7.731660e+15 d: 0.00e+00 g: 3.51e+12 h: 0.00e+00 rho: 0.00e+00 mu: 1.00e+04 li: 0 it: 5.87e-01 tt: 9.37e+00
- 1: f: 7.731660e+15 d: 7.73e+15 g: 0.00e+00 h: 1.20e+10 rho: 2.43e-11 mu: 5.00e+03 li: 1 it: 1.41e+01 tt: 2.35e+01
- 2: f: 7.731660e+15 d: 7.73e+15 g: 0.00e+00 h: 1.25e+10 rho: 1.70e-07 mu: 1.25e+03 li: 1 it: 1.86e+01 tt: 4.22e+01
- 3: f: 7.731660e+15 d:-2.39e+40 g: 0.00e+00 h: 3.53e+10 rho:-2.63e-13 mu: 1.56e+02 li: 1 it: 3.35e+01 tt: 7.57e+01
- 4: f: 7.731660e+15 d:-1.66e+39 g: 0.00e+00 h: 1.21e+11 rho:-6.58e-15 mu: 9.77e+00 li: 1 it: 3.86e+01 tt: 1.14e+02
- 5: f: 7.731660e+15 d:-3.57e+55 g: 0.00e+00 h: 5.00e+12 rho:-1.89e-14 mu: 3.05e-01 li: 1 it: 3.84e+01 tt: 1.53e+02
- 6: f: 7.731660e+15 d:-2.26e+35 g: 0.00e+00 h: 3.82e+12 rho:-1.77e-20 mu: 4.77e-03 li: 1 it: 3.45e+01 tt: 1.87e+02
- 7: f: 7.731660e+15 d:-5.31e+19 g: 0.00e+00 h: 1.22e+11 rho:-9.96e-21 mu: 3.73e-05 li: 1 it: 2.77e+01 tt: 2.15e+02
- 8: f: 1.784990e+08 d: 7.73e+15 g: 4.13e+07 h: 1.20e+10 rho: 1.00e+00 mu: 1.12e-04 li: 1 it: 1.13e+01 tt: 2.26e+02
- 9: f: 1.524025e+08 d: 2.61e+07 g: 5.81e+10 h: 2.41e+08 rho: 1.00e+00 mu: 3.35e-04 li: 1 it: 1.13e+01 tt: 2.37e+02
- 10: f: 1.488524e+08 d: 3.55e+06 g: 2.79e+09 h: 5.01e+08 rho: 1.00e+00 mu: 1.01e-03 li: 1 it: 1.09e+01 tt: 2.48e+02
+ - These messages were originally VLOG(2) and were mistakenly upgraded to
+ WARNINGs when the tolerances were reduced.
- After this change
+ Change-Id: I89dee666a09bc82cfa89b793dc0907268662f95e
+
+commit 9697a08a2bf29531671526b49df73bfbc0d7d237
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Sat Nov 23 10:03:37 2013 +0000
+
+ Defining CERES_FOUND in addition to Ceres_FOUND in CeresConfig.
- [inner] build: ./bin/bundle_adjuster --input ~/Downloads/problem-245-198739-pre.txt -num_iterations 10 -translation_sigma 0.01 -rotation_sigma 0.001 -point_sigma 0.1 -inner_iterations -num_threads 4
- 0: f: 7.731660e+15 d: 0.00e+00 g: 3.51e+12 h: 0.00e+00 rho: 0.00e+00 mu: 1.00e+04 li: 0 it: 5.66e-01 tt: 9.31e+00
- 1: f: 5.941477e+09 d: 7.73e+15 g: 1.20e+18 h: 1.20e+10 rho: 2.43e-11 mu: 5.00e+03 li: 1 it: 1.38e+01 tt: 2.32e+01
- 2: f: 3.341986e+08 d: 5.61e+09 g: 1.42e+14 h: 1.37e+09 rho: 9.38e-08 mu: 2.50e+03 li: 1 it: 1.30e+01 tt: 3.61e+01
- 3: f: 3.241492e+08 d: 1.00e+07 g: 3.64e+13 h: 8.26e+08 rho: 6.12e-08 mu: 1.25e+03 li: 1 it: 1.15e+01 tt: 4.77e+01
- 4: f: 3.152280e+08 d: 8.92e+06 g: 2.02e+13 h: 2.95e+08 rho: 1.56e-05 mu: 6.25e+02 li: 1 it: 1.11e+01 tt: 5.88e+01
- 5: f: 3.078535e+08 d: 7.37e+06 g: 9.72e+12 h: 4.57e+08 rho: 6.55e-09 mu: 3.13e+02 li: 1 it: 1.16e+01 tt: 7.04e+01
- 6: f: 3.025353e+08 d: 5.32e+06 g: 1.33e+13 h: 2.14e+08 rho: 7.21e-01 mu: 3.42e+02 li: 1 it: 1.14e+01 tt: 8.18e+01
- 7: f: 2.908298e+08 d: 1.17e+07 g: 5.97e+12 h: 7.25e+08 rho: 5.73e-01 mu: 3.43e+02 li: 1 it: 1.08e+01 tt: 9.26e+01
- 8: f: 2.803927e+08 d: 1.04e+07 g: 1.07e+12 h: 9.72e+07 rho: 5.27e-01 mu: 3.43e+02 li: 1 it: 1.03e+01 tt: 1.03e+02
- 9: f: 2.767074e+08 d: 3.69e+06 g: 2.10e+11 h: 7.35e+07 rho: 7.37e-01 mu: 3.84e+02 li: 1 it: 1.03e+01 tt: 1.13e+02
- 10: f: 2.744282e+08 d: 2.28e+06 g: 2.17e+11 h: 1.23e+08 rho: 3.11e-01 mu: 3.64e+02 li: 1 it: 9.61e+00 tt: 1.23e+02
+ - Previously we relied on FindPackage() to define Ceres_FOUND when
+ find_package(Ceres) was called.
+ - This is fine, but users might legitimately expect the variable to be
+ CERES_FOUND given the form of CERES_INCLUDE_DIRS/LIBRARIES.
+ - As there is an inconsistency in the CMake recommended names when
+ FindPackage() is called in Module vs Config form, we now explicltly
+ define both.
- Change-Id: I7c3b132f7ce62719795bfa489ec2276d0455cc97
+ Change-Id: I54bce9aa112b684d26b60a9ae4d11eb7925a6ee5
-commit 3e6ef29be6f3cd672a73cefb52838832a49e5427
+commit 66e15b41d80b155f333f099a0278d50312cdaa15
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 20 09:53:54 2013 -0700
+Date: Fri Nov 22 07:59:23 2013 -0800
- Update version history to reflect API changes
+ Lint cleanup from Jim Roseborough.
- Change-Id: I5ce744d72b991abba17b5cf9c6a1e1f158693151
+ Change-Id: I6ddbf5c3d66595d27f7967a309768e5f5dd7e1fd
-commit 1918453aeeae629be1f02eb333e91c4f728ace12
+commit 79bde35f29291cf464b59f3dc2dd9f1fa88776a9
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 19 14:15:48 2013 -0700
+Date: Thu Nov 21 21:33:51 2013 -0800
- Fix build breakage on old SuiteSparse.
-
- Errant semi colon is to blame.
+ SuiteSparse errors do not cause a fatal crash.
- Thanks to Timothy Langlois for reporting this.
+ 1. Move LinearSolverTerminationType to ceres::internal.
+ 2. Add FATAL_ERROR as a new enum to LinearSolverTerminationType.
+ 3. Pipe SuiteSparse errors via a LinearSolverTerminationType so
+ to distinguish between fatal and non-fatal errors.
+ 4. Update levenberg marquardt and dogleg strategies to deal
+ with FATAL_ERROR.
+ 5. Update trust_region_minimizer to terminate when FATAL_ERROR
+ is encountered.
+ 6. Remove SuiteSparse::SolveCholesky as it screws up the error
+ handling.
+ 7. Fix all clients calling SuiteSparse to handle the result of
+ SuiteSparse::Cholesky correctly.
+ 8. Remove fatal failures in SuiteSparse when symbolic factorization
+ fails.
+ 9. Fix all clients of SuiteSparse to deal with null symbolic factors.
- Change-Id: I57bb1cd69d78ab1897ead3627539a0da11b97455
-
-commit 8f33332c598d8209df73eb1c729e0abe2c890468
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Aug 18 23:25:00 2013 -0700
-
- Documentation update for 1.7.0rc2
+ This is a temporary fix to deal with some production problems. A more
+ extensive cleanup and testing regime will be put in place in a
+ subsequent CL.
- Change-Id: I6b0c19bed57b51a0f6591c60a4ae0d849c62451b
+ Change-Id: I1f60d539799dd95db7ecc340911e261fa4824f92
-commit ad2819a1afa94990022999a96eb158add68419e0
+commit a674e0f8534ea6948f70a72fe9718e07b3d039ff
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sat Aug 17 23:44:09 2013 -0700
+Date: Thu Nov 21 22:12:15 2013 -0800
- Fix breakage on old versions of SuiteSparse.
+ Fix corrector_test.cc.
- Thanks to Fisher Yu for reporting this.
+ Fix two death tests dealing with the sign of the gradient.
- Change-Id: Iefa89816cbb60e3512338a7c2a65655c017877ac
+ Change-Id: Ic91d54a64cc509307c94fce6d1fca083078936e2
-commit 880cba0939b2caa2641a5752373ffd47b64edd0f
-Author: Petter Strandmark <petter.strandmark@gmail.com>
-Date: Fri Aug 16 20:05:30 2013 +0200
+commit a8006af3110e98d64fb369e958fc00ec88d771a3
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Wed Nov 20 19:56:06 2013 +0000
- Fix warning C4373 in Visual Studio
+ Adding threads libraries to exported dependencies if using OpenMP.
- The warning occurs because an overridden function added a const
- to one argument.
+ - Previously we were only adding the flags to the link flags for the
+ Ceres project, which resulted in them not being exported. Thus
+ projects importing Ceres (if using OpenMP) would have to manually
+ specify them in addition to CERES_LIBRARIES.
- Change-Id: Idd24f7c6ab60064747104bfc75ae9bf112f61b3e
+ Change-Id: If0354cc07e84dbebfc870a8862e1a8ca64659791
-commit d61b68aaac3fa51b8fca8b1a268e83b0d5da01ea
+commit 6c0d96424e2c27326757936a3738f9efc37c6c24
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 16 17:02:56 2013 -0700
+Date: Wed Nov 20 11:52:01 2013 -0800
- Lint cleanups from William Rucklidge
+ Minor documentation fix.
- Change-Id: Ia4756ef97e65837d55838ee0b30806a234565bfd
+ Thanks to Satya Mallick.
+
+ Change-Id: I556f1c141bf16739d54450351b0f29fd4ea40014
-commit b22d063075ec545a59a25abd5d83e4642dc329c2
+commit 7747bb0e6b0e54366933ed75c1bcafe6a1109c3d
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 15 22:55:23 2013 -0700
+Date: Wed Nov 20 11:29:22 2013 -0800
- Reduce memory usage in covariance estimation.
-
- When using the SPARSE_QR algorithm, now a Q-less
- factorization is used. This results in significantly
- less memory usage.
+ Minor corrections to the documentation.
- The inversion of the semi-normal equations is now
- threaded using openmp. Indeed if one has SuiteSparse
- compiled with TBB, then both the factorization
- and the inversion are completely threaded.
+ Thanks to Satya Mallick for reporting these.
- Change-Id: Ia07591e48e7958d427ef91ff9e67662f6e982c21
+ Change-Id: Ia52e08a7e21d5247dc475cfbf10bf57265aa118f
-commit f258e4624f5bd86105ea28b9b92dd70a3f4a3a44
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Aug 15 14:50:08 2013 +0600
+commit 3fca2c4b2fae9abcaa9611f2bd3885ce6b11963b
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Mon Nov 18 10:26:49 2013 +0000
- Move most of suitesparse/cxsparse ifdef code to their headers
-
- Main purpose of this is to make implementation files free from
- endless ifdef blocks every time this libraries are needed to be
- included. This would hopefully prevent compilation errors in
- the future caused by missing ifdef around header include.
+ Decreasing update threshold for BFGS as per L-BFGS.
- This also includes some stubs added to suitesparse/cxsparse
- headers to make code even more free from ifdefs.
+ - Improves performance of BFGS on NIST, as per L-BFGS.
+ - Adding explanation of origin and purpose of Secant condition
+ tolerance check for Hessian update in (L)BFGS.
- Change-Id: Ic8554e7df31d8c4751583fe004b99e71b3c9087b
+ Change-Id: If57b9957d31d8629c772c19a069e1e56e727b350
-commit dc60d9c4519b5eb5e2cff8741680fecf4d6eb2c5
+commit 54fcbf893852272ba2158d6a56572a2eb3ccc41f
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 15 10:13:45 2013 -0700
+Date: Tue Nov 19 10:12:05 2013 -0800
- Fix broken android build.
+ Relax the requirements on loss functiond derivatives.
+
+ We now require that the first derivative of the loss function
+ be positive only if the second derivative is non-zero. This is
+ because when the second derivative is non-positive, we do not use
+ the second order correction suggested by BANS and instead use
+ a simpler first order strategy which does not use a division by
+ the gradient of the loss function.
- Change-Id: I6f27e3ef9bd678f7393c9f573491064978e9c368
+ Change-Id: I3d65713f152611998e196ff389a7081acfdfd8c1
-commit 367b65e17a541a9f29b9ea63682fe6f6b5b54074
+commit db98425b94c9eff9b125bf4a854545162e8c1aec
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 9 10:35:37 2013 -0700
+Date: Fri Nov 15 14:14:09 2013 -0800
- Multiple dense linear algebra backends.
+ Small bugfix to logging.h from Scott Ettinger.
- 1. When a LAPACK implementation is present, then
- DENSE_QR, DENSE_NORMAL_CHOLESKY and DENSE_SCHUR
- can use it for doing dense linear algebra operations.
-
- 2. The user can switch dense linear algebra libraries
- by setting Solver::Options::dense_linear_algebra_library_type.
-
- 3. Solver::Options::sparse_linear_algebra_library is now
- Solver::Options::sparse_linear_algebra_library_type to be consistent
- with all the other enums in Solver::Options.
-
- 4. Updated documentation as well as Solver::Summary::FullReport
- to reflect these changes.
-
- Change-Id: I5ab930bc15e90906b648bc399b551e6bd5d6498f
+ Change-Id: Ie6d51e7883adf36c6fc7a78ff95afab6a78e488b
-commit 080d1d04bdf722c3f602833c4c07ac1c5d26fcc0
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 12 16:28:37 2013 -0700
+commit 4d0e626b55f36ab8f44a4acc8157b85cfecd4673
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Fri Nov 15 13:53:44 2013 +0000
- Use more performant, less conservative Eigen solvers.
+ Fixing gflags HINTS variable names (adding missing “_DIR”).
- colPivHouseholderQR -> householderQR
- ldlt -> llt.
+ - The HINTS variables for gflags were incorrectly used as
+ GFLAGS_[INCLUDE/LIBRARY]_HINTS when they should have been
+ GFLAGS_[INCLUDE/LIBRARY]_DIR_HINTS as per the docs.
+ - Also removing a completed TODO in the main CMakeLists.
+ - Updating method of extracting current directory in CeresConfig.cmake
+ to avoid use of CMAKE_CURRENT_LIST_DIR, which was not present in
+ CMake =< v2.8.3.
- The resulting performance differences are significant enough
- to justify switching.
+ Change-Id: I42ae696e3b785febe48688d912f0f343e8947cb0
+
+commit bf4c1b76e4926c738fc805e9ff4be0ed584d9eee
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Thu Nov 14 21:27:20 2013 +0000
+
+ Decreasing threshold at which L-BFGS Hessian is updated.
- LAPACK's dgels routine used for solving linear least squares
- problems does not use pivoting either.
+ - Decreasing threshold at which L-BFGS Hessian is updated from 1e-10
+ to 1e-14 results in a very significant improvement in NIST scores
+ (43 -> 53 for CUBIC).
+ - Adding comment in FindPolynomialRoots() explaining why behaviour
+ is correct.
- Similarly, we are not actually using the fact that the matrix
- being factorized can be indefinite when using LDLT factorization, so
- its not clear that the performance hit is worth it.
+ Change-Id: If668e087e7a86d29659aa74e8528b192b604c841
+
+commit 7124c3474cd201134c3a3350b46aca468f1edafa
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Thu Nov 7 16:10:02 2013 +0000
+
+ Fixes for some line search bugs & corner cases.
+
+ - Increase precision of numeric values output in error messages to
+ allow for easier debugging.
+ - Ensure termination after Wolfe search bracketing phase if bracket
+ width has been shrunk to below tolerance.
+ - Cleaned up return value for BracketingPhase(), now false iff
+ optimisation should stop, true otherwise.
+ - Fix bug whereby we would mark a step size as satisfying the Wolfe
+ conditions when it did not due to numerical issues in the cost
+ function.
+ - Adding explanation of a subtlety in which a zoom could still be
+ acceptably invoked with bracket_low.f > bracket_high.f.
+ - Replacing hard check of a pre-condition of ZoomPhase() with a
+ conditional return if not satisfied to address issue whereby a
+ bracket could be incorrectly identified due to inconsistent values
+ & gradients returned from the cost function.
+ - Adding missing check for step size validity in line search minimizer.
+ - Adding ToDebugString() for FunctionSample.
+
+ Change-Id: Iad98e635749877f80c079ebad126bf022d82232d
+
+commit 54fc9423673886ac9ed3fe329a80f07544aeea70
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Thu Nov 14 11:42:00 2013 +0000
+
+ Removing incorrect specialisation of install dirs on Windows.
- These two changes result in Eigen being able to use blocking
- algorithms, which for Cholesky factorization, brings the performance
- closer to hardware optimized LAPACK. Similarly for dense QR
- factorization, on intel there is a 2x speedup.
+ - Previously on Windows the leaf include & lib install directories
+ passed to CeresConfig.cmake.in when configured where capitalised on
+ Windows.
+ - This capitalisation was incorrect, as the actual paths used are
+ specified in the install() statements and are always in the standard
+ lower-case form.
+ - This likely did not cause any issues previously as although NTFS is
+ case sensitive, the Win32 API is not, and most applications access
+ files through the Win32 API, and are thus not case-sensitive.
- Change-Id: I4459ee0fc8eb87d58e2b299dfaa9e656d539dc5e
+ Change-Id: I335b6e2d10a1c64f320c2a1a68eeda1b22344e73
-commit fb465a03b83fad2dceaea091ee3763c3dc6e83d2
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Mon Aug 5 22:35:14 2013 -0700
+commit fcbbb11e37386097b1427dc3aa89f264d6951ded
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Wed Nov 13 22:22:30 2013 +0000
- Fix compilation error caused by missing suitesparse headers
-
- Covariance implementation file used to unconditionally include
- SuiteSparseQR.hpp which caused compilation error in cases you
- don't have SuiteSuite installed to the system
+ Ensure build paths for dependencies are searched in FindPackage(Ceres)
- Moved the include to #ifdef block.
+ - Append to hint locations used by FindPackage scripts for public
+ dependencies (glog & Eigen) the locations of the dependencies when
+ Ceres was built.
+ - This means that the user should not have to supply them again when
+ using find_package(Ceres) even if they are installed in a
+ non-standard location.
- Change-Id: I3a52c0f81711b2b70ae625fe80b758ecb0817cc6
+ Change-Id: I9550de91025ba47f01f1ea3c3fefe80fe38d14ff
-commit 2460bf0733b4070e52d68a4a85046c1b20913e2c
-Author: Steven Lovegrove <stevenlovegrove@gmail.com>
-Date: Sun Jul 21 13:13:11 2013 -0400
+commit 7899e45d378f589a67ad8e042bf6a7cb7e15df00
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Wed Nov 13 21:08:27 2013 +0000
- Check GCC Version before adding -fast compiler option on OSX.
-
- -fast compiler option is only supported using Apple's GCC packaged with XCode.
- Other GCC versions will fail when this flag is enabled. This commit checks the
- GCC version on OSX and only enables this flag when < 4.3. Apple's GCC is
- currently 4.2.1 and a user is unlikely to install a non-apple version this old
- on OSX.
+ Fixing a documentation typo, DIRS -> DIR in HINTS variables.
- Change-Id: Ifca9149625c065cd16559d7e30c218a322cf79aa
+ Change-Id: I42b75a5e0b8a451c3a43ab29d0c14856e4b86ab8
-commit c5bcfc01af37b4f667be075c3c58dc024f3c7f06
+commit 1a041c35b780e60c3b497eb096b72ad20f47960e
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Jul 19 15:50:27 2013 -0700
+Date: Tue Nov 12 14:17:52 2013 -0800
- Lint fixes from Jim Roseborough.
+ Update to 1.8.0.
- Change-Id: If93e1972041b36410225a509e3c8c7c818f92124
+ Change-Id: Id42e594f03e3575d06e18c1ef66df64f43d86839
-commit 16924168ce0b3e29d9b1e16a08d2b3d2930e017a
+commit 36b26139296060511718b3ef0da03a52706db481
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Thu Nov 7 16:57:36 2013 +0000
+
+ Fix ordering of ParseCommandLineFlags() & InitGoogleTest() for Windows.
+
+ - On Windows gtest passes additional non-gflags command line flags
+ for death-tests, to avoid gflags invoking an error for these flags
+ InitGoogleTest() must be called before ParseCommandLineFlags() to
+ handle and remove them before gflags parses the remaining flags.
+
+ Change-Id: I0c705ecd3aa029b70a2589b592e6a2c192745c0e
+
+commit 8c155d51fab099ee7bf64f4bdbfeda82881925a5
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Jul 18 12:52:35 2013 -0700
+Date: Fri Nov 8 08:04:44 2013 -0800
- Update version from 1.6.0 -> 1.7.0rc1.
+ Speed up the application of robust loss functions.
+
+ Since we added special handling for the case for rho[2] < 0,
+ the bulk of CorrectJacobian is pointless in the common case.
+ So add a simple one dimensional loop which rescales the Jacobian.
+ This speeds up this method immensely.
+
+ The robustification of a Jacobian gets speeded up by > 50%.
- Change-Id: I420a8907142bffad0e3aa6c7196541ca2309c099
+ Change-Id: I97c4e897ccbb5521c053e1fb931c5d0d32f542c7
-commit 588228bdadcc0a1ffc55442a0672998241e53e09
+commit 58792dc8ee0e4b56331f33f753f1b1932c5c2960
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Jul 18 11:29:19 2013 -0700
+Date: Wed Nov 6 09:42:46 2013 -0800
- Add the ability to turn shared library compilation on and off
+ Update to 1.8.0rc2.
- Change-Id: Ib9eacfbc894bb2b66aafff3b930c63e2ad8a555e
+ Change-Id: Ifbf5312377bf1791a29aefd3edc3a765999c5824
-commit 6d93450cb563dc992cbc29ca069c886bf24bb458
+commit af04d7f18740faf452e9171af530aa1bdead44bb
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Jul 18 11:08:07 2013 -0700
+Date: Tue Nov 5 13:47:30 2013 -0800
- Fix build breakage on old versions of SuiteSparse.
+ Remove DCHECK_GE checks from fixed_array.h
- SuiteSparse_long is only defined in recent versions of SuiteSparse
- as the index variable type for large matrices. In older versions
- UF_long was used. Ubuntu still ships with an older version of
- SuiteSparse, so an ifdef is needed to fix the build.
+ This triggers -Wtype-limits warnings on comparisons
+ which are always true, since the test being done is
+ n >= 0, where n is of type size_t, which is always
+ true.
- This patch has been tested on mac and on linux with older and
- newer versions of SuiteSparse.
+ This causes problems when compiling Ceres on linux
+ with miniglog.
- Change-Id: I4ada86d7973784a79bde4afec13ce3ca4e8dc225
+ Change-Id: Ia1d1d1483e03469c71fde029b62ca6d84e9b27e0
-commit 42be9cafe6203745fb09d611773305433c117396
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Jul 18 08:02:08 2013 -0700
+commit b5be6b9c065a02158337ee7eacfdb8be811dec7f
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Tue Nov 5 13:10:27 2013 +0000
- Update documentation for Covariance
+ Cleaning up messages output when SuiteSparse is not found.
+
+ - Automatically generated failure message now provides more
+ information as to which sub-modules are missing.
- Change-Id: Ia4a7347ef8267b7107698d85fcbfc986111958dc
+ Change-Id: I6eed94af49263540b8f87917b75c41b8f49658a0
-commit 5a974716e111e4aa87a4840902b957060bd644fc
+commit 9ba0b352a282f08b1b6368a5690434407d7c81af
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Jun 7 22:38:30 2013 -0700
+Date: Tue Nov 5 13:04:56 2013 -0800
- Covariance estimation using SuiteSparseQR.
+ Lint and other cleanups from William Rucklidge
- Change-Id: I70d1686e3288fdde5f9723e832e15ffb857d6d85
+ Change-Id: I7fb23c2db85f0f121204560b79f1966f3d584431
-commit 719889b8b7a3ef6712516d169a4ce3a33d272fda
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Jul 17 11:31:08 2013 -0700
+commit 69bd65ff4368ce2841519f00ff48c5284c1743a3
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Mon Nov 4 23:01:14 2013 +0000
- Minor fixes
+ Downgrading warning messages when optional deps are not found.
- 1. Typo in c_api.h
- 2. The stream operator for FunctionSample is now in the ceres::internal namespace.
+ - Now when find_package() is called for a dependency without the
+ REQUIRED or QUIET qualifiers, we emit no priority (above STATUS, but
+ below WARNING) messages and continue.
- Change-Id: Id927a7a49c47d8903505535749ecca78cd2e83b3
+ Change-Id: I8cdeda7a8f6c91d45fb7f24fb366244c6c9b66e1
-commit 12cc164f79bb8a31e0eb3946e6f4898ac3c21c55
+commit b0a8731fcdde31e6c37a54e8c1e1c00f853c0d5c
Author: Alex Stewart <alexs.mac@gmail.com>
-Date: Wed Jul 17 12:08:33 2013 +0100
+Date: Mon Nov 4 20:32:40 2013 +0000
- Minor fix to reject a line search config with negative L-BFGS rank.
+ Removing duplicate SuiteSparse found message.
+
+ - Also flipping ordering of variables in
+ find_package_handle_standard_args() so that the automatically
+ generated message prints the include directories, not TRUE.
- Change-Id: Iad4c678efe574ef6696c34bd2a0ce61a504c7344
+ Change-Id: I2bf62eacd5c96f27152e9542b9a74651243a584e
-commit 9aa0e3cf7243a2e837bbfa22d4677010463f6a4e
+commit 6fed9fe0de9d1737095c24e19ad8df9735b7e572
Author: Alex Stewart <alexs.mac@gmail.com>
-Date: Fri Jul 5 20:22:37 2013 +0100
+Date: Mon Nov 4 18:33:05 2013 +0000
- Adding Wolfe line search algorithm and full BFGS search direction options.
+ Fix FindPackage scripts to emit warnings, not errors if not found.
- Change-Id: I9d3fb117805bdfa5bc33613368f45ae8f10e0d79
+ - Previously we used message priority: SEND_ERROR when a package was
+ not found and find_package() was called without QUIET or REQUIRED,
+ which emits an error message, and prevents generation, but continues
+ configuration.
+ - The fact SEND_ERROR induces an error message was confusing for users
+ as it implies that something bad has happened and they cannot
+ continue, when in fact we were disabling the option in question
+ and were thus able to continue, all they had to do was re-configure.
+
+ - This commit also reorders the search lists for includes/libraries
+ so that we always search user installed locations (e.g. /usr/local)
+ before system installed locations. Thus we will now always prefer
+ a user install to a system install if both are available, which is
+ likely to be the users desired intention.
+
+ Change-Id: Ide84919f27d3373f31282f70c685720cd77a6723
-commit 51c772c843ccecca006c706a9f64b8cbaf5416f9
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Jul 16 16:42:52 2013 -0700
+commit cada337149cbc4b9e6f2bae14593b87ecf8f1a5c
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Mon Nov 4 18:08:24 2013 +0000
- householderQR -> colPivHouseholderQR.
+ Fixing CXSparse include directories statement.
+
+ - Reported as issue #135:
+ https://code.google.com/p/ceres-solver/issues/detail?id=135.
+ - CXSPARSE_INCLUDE was the legacy include directory variable, since
+ the buildsystem updates we now use the CMake standard:
+ CXSPARSE_INCLUDE_DIRS.
- Change-Id: Ida623e853711f665e7a9d3b140a93e861591f96d
+ Change-Id: Iab0c2de14d524bb9e9da230bc574b5e6f09e1f31
-commit c2c6411d16db95cde0cc3a7a80bac87266234bb7
+commit c71085ed326239dc2d318d848ded9a99e4e3c107
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sat Jul 13 18:47:49 2013 -0700
+Date: Thu Oct 31 13:56:38 2013 -0700
- DENSE_QR solver now uses non pivoting QR decomposition.
+ Update to 1.8.0rc1.
- Change-Id: I9099221448ccf71d0de20b9f652405009a6c24c5
+ Change-Id: Iaa10fd5a20be2ef84aca0119306c44669d87cc5d
-commit 3c2ad4018c8d2271434b9ff2bd05437b96f4927c
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Jul 15 08:09:38 2013 -0700
+commit 88a703f44ff0d6d5d4601584fa77f5ce853025f4
+Author: Petter Strandmark <petter.strandmark@gmail.com>
+Date: Thu Oct 31 21:13:48 2013 +0100
- Speed up Automatic differentiation by 7%.
+ Fix compilation in Visual C++ 2013.
- 1. Templatize Make1stOrderPerturbation.
- 2. Convert a hard CHECK into DCHECK.
+ I had to fix the following things to make Ceres compile in 2013:
+ * Not link to 'm' (GNU math library).
+ * Excplicitly convert an std::ostream to bool.
+ * Include <algorithm> for std::max.
- Change-Id: I02cd67f2b87bc5722f1a090057d55f23e98d2c3b
+ Change-Id: I3ff65413baf8711364360d46dd71fd553fa63e72
-commit 0a07fbf8731adcdce98c8e73127d379199341132
+commit f06b9face5bfbbc2b338aa2460bee2298a3865c5
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Jul 10 11:57:35 2013 -0700
+Date: Sun Oct 27 21:38:13 2013 -0700
- Use ATLAS as the example BLAS in building.rst
+ Add support for multiple visibility clustering algorithms.
+
+ The original visibility based preconditioning paper and
+ implementation only used the canonical views algorithm.
+
+ This algorithm for large dense graphs can be particularly
+ expensive. As its worst case complexity is cubic in size
+ of the graph.
+
+ Further, for many uses the SCHUR_JACOBI preconditioner
+ was both effective enough while being cheap. It however
+ suffers from a fatal flaw. If the camera parameter blocks
+ are split between two or more parameter blocks, e.g,
+ extrinsics and intrinsics. The preconditioner because
+ it is block diagonal will not capture the interactions
+ between them.
- OpenBLAS has subtle issues releated to threading. It
- conflicts with the use of threads in the other parts of
- the application.
+ Using CLUSTER_JACOBI or CLUSTER_TRIDIAGONAL will fix
+ this problem but as mentioned above this can be quite
+ expensive depending on the problem.
- Careful users can still use it by disabling threads via
- an environment variable, but by default we want to use
- a BLAS/LAPACK that does not suffer from these problems.
+ This change extends the visibility based preconditioner
+ to allow for multiple clustering algorithms. And adds
+ a simple thresholded single linkage clustering algorithm
+ which allows you to construct versions of CLUSTER_JACOBI
+ and CLUSTER_TRIDIAGONAL preconditioners that are cheap
+ to construct and are more effective than SCHUR_JACOBI.
- Change-Id: I8c1c0ed0b526453564c5f9ea69b646fac32fe027
+ Currently the constants controlling the threshold above
+ which edges are considered in the single linkage algorithm
+ are not exposed. This would be done in a future change.
+
+ Change-Id: I7ddc36790943f24b19c7f08b10694ae9a822f5c9
-commit aee5597acf9c2c064977e937f52689254ebd1a39
+commit 5a161a2b9653489ee9040f054b24df971e6b9bbc
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Jul 9 23:30:07 2013 -0700
+Date: Tue Oct 29 22:08:15 2013 -0700
- Minor fix to curve_fitting.c
+ Template specializations for PartitionedMatrixView.
+
+ This speeds up the matrix vector products in the
+ IterativeSchurSolver by upto 40%.
- Change-Id: Ib3669a5c4c73178b088dc1e80141f844f807b179
+ Change-Id: Ib5e8d77c7269cf5ffdd2d161893734bb6d38215d
-commit bd82f82c3afeb3c57fa03f61fdbb0388f9ed8b02
+commit e5ce1170bc9993085c81a788e16eb48f1b2fdb97
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Jul 9 23:19:09 2013 -0700
+Date: Tue Oct 29 07:40:51 2013 -0700
- More CMake file cleanup.
+ Minor bug fix to autodiff.h
- Reduce the verbosity of the Cmake file. All the "Checking for"
- messages have been removed since we log both success and failures.
+ Change-Id: Ib41050a2f2ba1898c71ff19d74f8eca2496212c0
+
+commit 9e9a7d6ca0e75727293f94452d602f02b56d10ba
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Oct 29 06:54:44 2013 -0700
+
+ Documentation update.
- Further, UFConfig is only searched for if SuiteSparse_config cannot
- be found.
+ Add documentation for the new methods added to Problem.
+ Fix a bunch of ReST bugs.
- Change-Id: I601a6ffc808e566ff78ce232c86519ef413f0b33
+ Change-Id: I8a79a84040cfa8a679cc5355baccbe6d69bc9e70
-commit 9f4552b6475616df7e60681e60cd5afebb45a4ea
+commit c6bafdd02c33ec0ccb705578d83e4f601ddeedea
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Jul 9 00:10:08 2013 -0700
+Date: Mon Oct 28 19:38:08 2013 -0700
- Stop CMake from trying to detect OpenMP when using Clang.
+ Comments from Jim Roseborough.
+
+ 1. Fix the tolerance on the rotation matrix conversion test.
+ 2. Fix some out of date comments.
- Change-Id: Ie14c6466475b401ba35dbf13adc2e8701999c969
+ Change-Id: I65e80da1f96d7b4d9ac0630ad8cb708c41739840
-commit 6e8bd501b25dc308df7b1a5eed16edfd8442002e
+commit fda69b52130955479591e8f03f97b1cfceca369f
Author: Keir Mierle <mierle@gmail.com>
-Date: Thu May 23 01:49:08 2013 -0700
+Date: Thu Oct 10 00:25:24 2013 -0700
- Extend the C API to support loss functions
+ Export the structure of a problem to the public API
+
+ This adds three new public methods to ceres::Problem:
- This extends the C API to support loss functions. Both
- user-supplied cost functions as well as the stock Ceres cost
- functions (Cauchy, Huber, etc) are supported. In addition, this
- adds a simple unit test for the C API.
+ Problem::GetResidualBlocks()
+ Problem::GetParameterBlocksForResidualBlock()
+ Problem::GetResidualBlocksForParameterBlock()
- Supporting loss functions required changing the signature of the
- ceres_add_residual_block() function to also take a thunk for the
- loss function.
+ These permit access to the underlying graph structure of the problem.
- Change-Id: Iefa58cf709adbb8f24588e5eb6aed9aef46b6d73
+ Change-Id: I55a4c7f0e5f325f140cb4830e7a7070554594650
-commit 1ab7fde626c3d3ac02664183f21fedd397785bea
+commit 63bcdffa7d188b8d8c5309a62c255ba33f061764
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Jul 8 10:03:49 2013 -0700
+Date: Sun Oct 27 21:34:13 2013 -0700
- Update gmock and gtest to the latest svn versions.
+ Add the 2_d_d SchurEliminator specialization.
- This fixes a variety of mac/clang/c++11 issues.
+ This occurs far too often in bundle adjustment problems to be ignored.
- Change-Id: I52e76d733cd53c9bb2fda125e51a6b58a90e41b3
+ Change-Id: Ib137f1566acf5fffa63e50a55fe8e78ea9eb1c14
-commit eeedd2e191f5ce404453c735061ad13bd45b939b
+commit 602096c91363a0b9384f887a15c82e2dac1fb923
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Jul 7 23:04:31 2013 -0700
+Date: Sun Oct 27 05:09:38 2013 -0700
- Rationalize some of the variable names in Solver::Options.
+ Move CERES_HASH_NAMESPACE macros to collections_port.h
- lm_max_diagonal -> max_lm_diagonal
- lm_min_diagonal -> min_lm_diagonal
- linear_solver_max_num_iterations -> max_linear_solver_iterations
- linear_solver_min_num_iterations -> min_linear_solver_iterations
+ Now that we have a clearer understanding of the naming rules
+ there is no need for these macro definitions to be done in
+ the cmake file.
- This follows the pattern for the other parameters in Solver::Options
- where, the max/min is the first word followed by the name of the
- parameter.
+ This cleans up the compilation command line.
- Change-Id: I0893610fceb6b7983fdb458a65522ba7079596a7
+ Change-Id: Idc8fc7a7c9376e021dc4790af66e599105351917
-commit 7a8f79792467e56012d43b5f9aa7aefce14d5ee9
+commit f6b67df54ad6daa7036f5b6619243f722d678892
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Jul 3 09:03:55 2013 -0700
+Date: Fri Oct 25 06:24:19 2013 -0700
- Lint fixes
+ Fix handling of unordered_map/unordered_set on OSX 10.9.0.
- Change-Id: Ic453597488ef92723a81a224e7443e8f454b25da
-
-commit 67ccb7379e7eab709480e227323ea48ea91e7ccc
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Jul 3 06:28:34 2013 -0700
-
- Fix broken build.
+ Depending on the compiler + standard library combination,
+ unordered_map/set may or may not be available. If available
+ they maybe in the std or the std::tr1 namespaces.
- Change-Id: Ieb122bb96d5776f962fff6d6e9345dfc855bfed7
-
-commit 4f010b2db02f22cee8243ed83a49e63a305dbb76
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Jul 1 08:01:01 2013 -0700
-
- Improve Summary::FullReport when line search is used.
+ Apple switched to using libc++ with 10.9.0 which places
+ unordered_map in std, breaking our assumptions about the
+ platform.
- Disable reporting of preconditioner when direct factorization
- is being used.
+ This change refactors our logic for dealing with the namespace
+ switching, making it a three state thing rather than two. There
+ are three defines now, CERES_NO_UNORDERED_MAP, CERES_STD_UNORDERED_MAP
+ and CERES_TR1_UNORDERED_MAP. Earlier the first two were conflated
+ into one, leading to the breakage.
- Change-Id: Id264d2292c5cab608724a6a8fab5d588db950468
+ Change-Id: I904fe8c49529169bdefa9f2ee6d629e7eab0b855
-commit 09244015e304b0ebfb2f2399edd2d97e3b9dcd8f
+commit 21d6a99fe68e99fa51db32d55f587b42ef9a476c
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Jun 30 14:33:23 2013 -0700
+Date: Fri Oct 25 10:20:24 2013 -0700
- Expose line search parameters in Solver::Options.
+ Fix AngleAxisToRotationMatrix near zero.
+
+ The Taylor series approximation had its sign flipped and the
+ tests did not catch it since we were switching exactly at zero,
+ which was not getting triggered.
- Change-Id: Ifc52980976e7bac73c8164d80518a5a19db1b79d
+ This changes modifies the tolerance, adds a test that triggers
+ and fixes the bug.
+
+ Thanks to Michael Samples for reporting this.
+
+ Change-Id: I6f92f6348e5d4421ffe194fba92c04285449484c
-commit 1c70ae9aa626e591cda987a970c240dd40d23a69
+commit 0e2743e24d013b25109396cfa0d8d0f1e8e84964
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Jun 30 12:50:43 2013 -0700
+Date: Wed Oct 23 14:51:07 2013 -0700
- Fix Solver::Summary when line search is used.
+ Add BlockRandomAccessDiagonalMatrix.
- Also enable line search in bundle_adjuster.
+ This class is used in the SchurJacobiPreconditioner for
+ storing the preconditioner matrix. Using it speeds up
+ the computation of the preconditioner by ~15% due to
+ the elimination of a hash table lookup.
- Change-Id: Ic4343a4334b9f5a6fdeab38d4e3e1f6932bbc601
+ Change-Id: Iba2b34aad0d9eb9bcb7f6e6fad16aa416aac0d2a
-commit 70b06c89c7491d7749957c8454769bfcb0108a97
+commit 6a2bcaa1d55d38bc10d043f1458657caac2be7a7
Author: Alex Stewart <alexs.mac@gmail.com>
-Date: Sun Jun 30 18:49:56 2013 +0100
+Date: Wed Oct 23 14:06:44 2013 +0100
- Fix update of L-BFGS history buffers after they become full.
-
- Previously there was an assignment dimension mismatch in the
- history update; thus, over time, the history would contain
- (only) replicated copies of the (max_num_corrections_ -1)-th
- update and the most recent update.
+ Adding explicit link to libm for pure-C curve fitting example.
- Change-Id: I26203acf689686d41a5029c675ebbe001fe05d90
-
-commit a427c877f968d951b3cdcb5f5298deaf84647830
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Jun 24 17:50:56 2013 -0700
-
- Lint cleanup.
+ - Any pure-C program #including <math.h> will need to link against
+ libm, some compilers will let an indirect link slide (via Ceres in
+ this case) but some won't.
- Change-Id: Ie489f1ff182d99251ed8c0728cc6ea8e1c262ce0
+ Change-Id: I6890702fa0d2c3fbb747f0f81fc3fa3631839de4
diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript
index 164aedfe415..2573a9742ad 100644
--- a/extern/libmv/third_party/ceres/SConscript
+++ b/extern/libmv/third_party/ceres/SConscript
@@ -14,11 +14,10 @@ defs = []
src += env.Glob('internal/ceres/*.cc')
src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc')
+src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc')
#src += env.Glob('internal/ceres/generated/*.cc')
defs.append('CERES_HAVE_PTHREAD')
-defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
-defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_NO_CXSPARSE')
defs.append('CERES_NO_LAPACK')
@@ -28,8 +27,36 @@ defs.append('CERES_HAVE_RWLOCK')
if env['WITH_BF_OPENMP']:
defs.append('CERES_USE_OPENMP')
-if 'Mac OS X 10.5' in env['MACOSX_SDK']:
- defs.append('CERES_NO_TR1')
+conf = Configure(env)
+if conf.CheckCXXHeader("unordered_map"):
+ # Even so we've found unordered_map header file it doesn't
+ # mean unordered_map and unordered_set will be declared in
+ # std namespace.
+ #
+ # Namely, MSVC 2008 have unordered_map header which declares
+ # unordered_map class in std::tr1 namespace. In order to support
+ # this, we do extra check to see which exactly namespace is
+ # to be used.
+
+ if conf.CheckType('std::unordered_map<int, int>', language = 'CXX', includes="#include <unordered_map>"):
+ defs.append('CERES_STD_UNORDERED_MAP')
+ print("-- Found unordered_map/set in std namespace.")
+ elif conf.CheckType('std::tr1::unordered_map<int, int>', language = 'CXX', includes="#include <unordered_map>"):
+ defs.append('CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE')
+ print("-- Found unordered_map/set in std::tr1 namespace.")
+ else:
+ print("-- Found <unordered_map> but can not find neither std::unordered_map nor std::tr1::unordered_map.")
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CERES_NO_UNORDERED_MAP')
+elif conf.CheckCXXHeader("tr1/unordered_map"):
+ defs.append('CERES_TR1_UNORDERED_MAP')
+ print("-- Found unordered_map/set in std::tr1 namespace.")
+else:
+ print("-- Unable to find <unordered_map> or <tr1/unordered_map>. ")
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CERES_NO_UNORDERED_MAP')
+
+env = conf.Finish()
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh
index a6f040b6d29..d937ed46945 100755
--- a/extern/libmv/third_party/ceres/bundle.sh
+++ b/extern/libmv/third_party/ceres/bundle.sh
@@ -43,8 +43,11 @@ done
rm -rf $tmp
-sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | grep -v -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d`
-generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//#\t\t/' | grep -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d`
+sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | \
+ grep -v -E 'schur_eliminator_[0-9]_[0-9d]_[0-9d].cc' | \
+ grep -v -E 'partitioned_matrix_view_[0-9]_[0-9d]_[0-9d].cc' | sort -d`
+generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//#\t\t/' | \
+ grep -E 'schur_eliminator_[0-9]_[0-9d]_[0-9d].cc|partitioned_matrix_view_[0-9]_[0-9d]_[0-9d].cc' | sort -d`
headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d`
src_dir=`find ./internal -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq`
@@ -171,23 +174,54 @@ if(WITH_OPENMP)
)
endif()
-if(MSVC10)
- add_definitions(
- -D"CERES_HASH_NAMESPACE_START=namespace std {"
- -D"CERES_HASH_NAMESPACE_END=}"
- )
+include(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(unordered_map HAVE_STD_UNORDERED_MAP_HEADER)
+if(HAVE_STD_UNORDERED_MAP_HEADER)
+ # Even so we've found unordered_map header file it doesn't
+ # mean unordered_map and unordered_set will be declared in
+ # std namespace.
+ #
+ # Namely, MSVC 2008 have unordered_map header which declares
+ # unordered_map class in std::tr1 namespace. In order to support
+ # this, we do extra check to see which exactly namespace is
+ # to be used.
+
+ include(CheckCXXSourceCompiles)
+ CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+ int main() {
+ std::unordered_map<int, int> map;
+ return 0;
+ }"
+ HAVE_UNURDERED_MAP_IN_STD_NAMESPACE)
+ if(HAVE_UNURDERED_MAP_IN_STD_NAMESPACE)
+ add_definitions(-DCERES_STD_UNORDERED_MAP)
+ message(STATUS "Found unordered_map/set in std namespace.")
+ else()
+ CHECK_CXX_SOURCE_COMPILES("#include <unordered_map>
+ int main() {
+ std::tr1::unordered_map<int, int> map;
+ return 0;
+ }"
+ HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE)
+ if(HAVE_UNURDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+ message(STATUS "Found unordered_map/set in std::tr1 namespace.")
+ else()
+ message(STATUS "Found <unordered_map> but cannot find either std::unordered_map "
+ "or std::tr1::unordered_map.")
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ add_definitions(-DCERES_NO_UNORDERED_MAP)
+ endif()
+ endif()
else()
- add_definitions(
- -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
- -D"CERES_HASH_NAMESPACE_END=}}"
- )
-endif()
-
-if(APPLE)
- if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5")
- add_definitions(
- -DCERES_NO_TR1
- )
+ CHECK_INCLUDE_FILE_CXX("tr1/unordered_map" UNORDERED_MAP_IN_TR1_NAMESPACE)
+ if(UNORDERED_MAP_IN_TR1_NAMESPACE)
+ add_definitions(-DCERES_TR1_UNORDERED_MAP)
+ message(STATUS "Found unordered_map/set in std::tr1 namespace.")
+ else()
+ message(STATUS "Unable to find <unordered_map> or <tr1/unordered_map>. ")
+ message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
+ add_definitions(-DCERES_NO_UNORDERED_MAP)
endif()
endif()
@@ -211,11 +245,10 @@ defs = []
$src
src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc')
+src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc')
#src += env.Glob('internal/ceres/generated/*.cc')
defs.append('CERES_HAVE_PTHREAD')
-defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
-defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_NO_CXSPARSE')
defs.append('CERES_NO_LAPACK')
@@ -225,8 +258,36 @@ defs.append('CERES_HAVE_RWLOCK')
if env['WITH_BF_OPENMP']:
defs.append('CERES_USE_OPENMP')
-if 'Mac OS X 10.5' in env['MACOSX_SDK']:
- defs.append('CERES_NO_TR1')
+conf = Configure(env)
+if conf.CheckCXXHeader("unordered_map"):
+ # Even so we've found unordered_map header file it doesn't
+ # mean unordered_map and unordered_set will be declared in
+ # std namespace.
+ #
+ # Namely, MSVC 2008 have unordered_map header which declares
+ # unordered_map class in std::tr1 namespace. In order to support
+ # this, we do extra check to see which exactly namespace is
+ # to be used.
+
+ if conf.CheckType('std::unordered_map<int, int>', language = 'CXX', includes="#include <unordered_map>"):
+ defs.append('CERES_STD_UNORDERED_MAP')
+ print("-- Found unordered_map/set in std namespace.")
+ elif conf.CheckType('std::tr1::unordered_map<int, int>', language = 'CXX', includes="#include <unordered_map>"):
+ defs.append('CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE')
+ print("-- Found unordered_map/set in std::tr1 namespace.")
+ else:
+ print("-- Found <unordered_map> but can not find neither std::unordered_map nor std::tr1::unordered_map.")
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CERES_NO_UNORDERED_MAP')
+elif conf.CheckCXXHeader("tr1/unordered_map"):
+ defs.append('CERES_TR1_UNORDERED_MAP')
+ print("-- Found unordered_map/set in std::tr1 namespace.")
+else:
+ print("-- Unable to find <unordered_map> or <tr1/unordered_map>. ")
+ print("-- Replacing unordered_map/set with map/set (warning: slower!)")
+ defs.append('CERES_NO_UNORDERED_MAP')
+
+env = conf.Finish()
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt
index 071ccda655c..0ec7fc5354e 100644
--- a/extern/libmv/third_party/ceres/files.txt
+++ b/extern/libmv/third_party/ceres/files.txt
@@ -8,6 +8,7 @@ include/ceres/cost_function_to_functor.h
include/ceres/covariance.h
include/ceres/crs_matrix.h
include/ceres/dynamic_autodiff_cost_function.h
+include/ceres/dynamic_numeric_diff_cost_function.h
include/ceres/fpclassify.h
include/ceres/gradient_checker.h
include/ceres/internal/autodiff.h
@@ -46,6 +47,8 @@ internal/ceres/block_random_access_crs_matrix.cc
internal/ceres/block_random_access_crs_matrix.h
internal/ceres/block_random_access_dense_matrix.cc
internal/ceres/block_random_access_dense_matrix.h
+internal/ceres/block_random_access_diagonal_matrix.cc
+internal/ceres/block_random_access_diagonal_matrix.h
internal/ceres/block_random_access_matrix.cc
internal/ceres/block_random_access_matrix.h
internal/ceres/block_random_access_sparse_matrix.cc
@@ -96,6 +99,23 @@ internal/ceres/evaluator.h
internal/ceres/execution_summary.h
internal/ceres/file.cc
internal/ceres/file.h
+internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
+internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
+internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
+internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
+internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
+internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
+internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
+internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
+internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
+internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
+internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
+internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
+internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
+internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
+internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
+internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
+internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
internal/ceres/generated/schur_eliminator_2_2_2.cc
internal/ceres/generated/schur_eliminator_2_2_3.cc
internal/ceres/generated/schur_eliminator_2_2_4.cc
@@ -107,12 +127,14 @@ internal/ceres/generated/schur_eliminator_2_3_d.cc
internal/ceres/generated/schur_eliminator_2_4_3.cc
internal/ceres/generated/schur_eliminator_2_4_4.cc
internal/ceres/generated/schur_eliminator_2_4_d.cc
+internal/ceres/generated/schur_eliminator_2_d_d.cc
internal/ceres/generated/schur_eliminator_4_4_2.cc
internal/ceres/generated/schur_eliminator_4_4_3.cc
internal/ceres/generated/schur_eliminator_4_4_4.cc
internal/ceres/generated/schur_eliminator_4_4_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/generate_eliminator_specialization.py
+internal/ceres/generate_partitioned_matrix_view_specializations.py
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/gradient_checking_cost_function.h
internal/ceres/graph_algorithms.h
@@ -154,6 +176,7 @@ internal/ceres/parameter_block_ordering.cc
internal/ceres/parameter_block_ordering.h
internal/ceres/partitioned_matrix_view.cc
internal/ceres/partitioned_matrix_view.h
+internal/ceres/partitioned_matrix_view_impl.h
internal/ceres/polynomial.cc
internal/ceres/polynomial.h
internal/ceres/preconditioner.cc
@@ -169,8 +192,6 @@ internal/ceres/residual_block.cc
internal/ceres/residual_block.h
internal/ceres/residual_block_utils.cc
internal/ceres/residual_block_utils.h
-internal/ceres/runtime_numeric_diff_cost_function.cc
-internal/ceres/runtime_numeric_diff_cost_function.h
internal/ceres/schur_complement_solver.cc
internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.cc
@@ -180,6 +201,8 @@ internal/ceres/schur_jacobi_preconditioner.cc
internal/ceres/schur_jacobi_preconditioner.h
internal/ceres/scratch_evaluate_preparer.cc
internal/ceres/scratch_evaluate_preparer.h
+internal/ceres/single_linkage_clustering.cc
+internal/ceres/single_linkage_clustering.h
internal/ceres/small_blas.h
internal/ceres/solver.cc
internal/ceres/solver_impl.cc
diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
index 371a11f71ec..7c0fa79ad0b 100644
--- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
@@ -96,7 +96,7 @@
// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
// 1-dimensional output from two arguments, both 2-dimensional.
//
-// The autodiff cost function also supports cost functions with a
+// AutoDiffCostFunction also supports cost functions with a
// runtime-determined number of residuals. For example:
//
// CostFunction* cost_function
@@ -110,8 +110,9 @@
// Dimension of x ------------------------------------+ |
// Dimension of y ---------------------------------------+
//
-// The framework can currently accommodate cost functions of up to 6 independent
-// variables, and there is no limit on the dimensionality of each of them.
+// The framework can currently accommodate cost functions of up to 10
+// independent variables, and there is no limit on the dimensionality
+// of each of them.
//
// WARNING #1: Since the functor will get instantiated with different types for
// T, you must to convert from other numeric types to T before mixing
@@ -145,13 +146,13 @@ namespace ceres {
//
// The constructors take ownership of the cost functor.
//
-// If the number of residuals (argument "M" below) is ceres::DYNAMIC, then the
-// two-argument constructor must be used. The second constructor takes a number
-// of residuals (in addition to the templated number of residuals). This allows
-// for varying the number of residuals for a single autodiff cost function at
-// runtime.
+// If the number of residuals (argument kNumResiduals below) is
+// ceres::DYNAMIC, then the two-argument constructor must be used. The
+// second constructor takes a number of residuals (in addition to the
+// templated number of residuals). This allows for varying the number
+// of residuals for a single autodiff cost function at runtime.
template <typename CostFunctor,
- int M, // Number of residuals, or ceres::DYNAMIC.
+ int kNumResiduals, // Number of residuals, or ceres::DYNAMIC.
int N0, // Number of parameters in block 0.
int N1 = 0, // Number of parameters in block 1.
int N2 = 0, // Number of parameters in block 2.
@@ -162,28 +163,32 @@ template <typename CostFunctor,
int N7 = 0, // Number of parameters in block 7.
int N8 = 0, // Number of parameters in block 8.
int N9 = 0> // Number of parameters in block 9.
-class AutoDiffCostFunction : public SizedCostFunction<M,
+class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
N0, N1, N2, N3, N4,
N5, N6, N7, N8, N9> {
public:
// Takes ownership of functor. Uses the template-provided value for the
- // number of residuals ("M").
+ // number of residuals ("kNumResiduals").
explicit AutoDiffCostFunction(CostFunctor* functor)
: functor_(functor) {
- CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the "
- << "number of residuals is set to ceres::DYNAMIC.";
+ CHECK_NE(kNumResiduals, DYNAMIC)
+ << "Can't run the fixed-size constructor if the "
+ << "number of residuals is set to ceres::DYNAMIC.";
}
- // Takes ownership of functor. Ignores the template-provided number of
- // residuals ("M") in favor of the "num_residuals" argument provided.
+ // Takes ownership of functor. Ignores the template-provided
+ // kNumResiduals in favor of the "num_residuals" argument provided.
//
// This allows for having autodiff cost functions which return varying
// numbers of residuals at runtime.
AutoDiffCostFunction(CostFunctor* functor, int num_residuals)
: functor_(functor) {
- CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the "
- << "number of residuals is not ceres::DYNAMIC.";
- SizedCostFunction<M, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
+ CHECK_EQ(kNumResiduals, DYNAMIC)
+ << "Can't run the dynamic-size constructor if the "
+ << "number of residuals is not ceres::DYNAMIC.";
+ SizedCostFunction<kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9>
::set_num_residuals(num_residuals);
}
@@ -206,8 +211,9 @@ class AutoDiffCostFunction : public SizedCostFunction<M,
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(
*functor_,
parameters,
- SizedCostFunction<M, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
- ::num_residuals(),
+ SizedCostFunction<kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9>::num_residuals(),
residuals,
jacobians);
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/ceres.h b/extern/libmv/third_party/ceres/include/ceres/ceres.h
index 61b8b94dcaa..fca4907d384 100644
--- a/extern/libmv/third_party/ceres/include/ceres/ceres.h
+++ b/extern/libmv/third_party/ceres/include/ceres/ceres.h
@@ -34,8 +34,8 @@
#ifndef CERES_PUBLIC_CERES_H_
#define CERES_PUBLIC_CERES_H_
-#define CERES_VERSION 1.7.0
-#define CERES_ABI_VERSION 1.7.0
+#define CERES_VERSION 1.8.0
+#define CERES_ABI_VERSION 1.8.0
#include "ceres/autodiff_cost_function.h"
#include "ceres/autodiff_local_parameterization.h"
@@ -43,6 +43,8 @@
#include "ceres/cost_function_to_functor.h"
#include "ceres/covariance.h"
#include "ceres/crs_matrix.h"
+#include "ceres/dynamic_autodiff_cost_function.h"
+#include "ceres/dynamic_numeric_diff_cost_function.h"
#include "ceres/iteration_callback.h"
#include "ceres/jet.h"
#include "ceres/local_parameterization.h"
diff --git a/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h
index 5d8f188e5a7..f9342cdbab9 100644
--- a/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2012 Google Inc. All rights reserved.
+// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -26,18 +26,17 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
-// Author: mierle@gmail.com (Keir Mierle)
-// sameeragarwal@google.com (Sameer Agarwal)
-// thadh@gmail.com (Thad Hughes)
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+// mierle@gmail.com (Keir Mierle)
//
// This autodiff implementation differs from the one found in
-// autodiff_cost_function.h by supporting autodiff on cost functions with
-// variable numbers of parameters with variable sizes. With the other
-// implementation, all the sizes (both the number of parameter blocks and the
-// size of each block) must be fixed at compile time.
+// autodiff_cost_function.h by supporting autodiff on cost functions
+// with variable numbers of parameters with variable sizes. With the
+// other implementation, all the sizes (both the number of parameter
+// blocks and the size of each block) must be fixed at compile time.
//
-// The functor API differs slightly from the API for fixed size autodiff; the
-// expected interface for the cost functors is:
+// The functor API differs slightly from the API for fixed size
+// autodiff; the expected interface for the cost functors is:
//
// struct MyCostFunctor {
// template<typename T>
@@ -46,8 +45,9 @@
// }
// }
//
-// Since the sizing of the parameters is done at runtime, you must also specify
-// the sizes after creating the dynamic autodiff cost function. For example:
+// Since the sizing of the parameters is done at runtime, you must
+// also specify the sizes after creating the dynamic autodiff cost
+// function. For example:
//
// DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
// new MyCostFunctor());
@@ -55,10 +55,11 @@
// cost_function.AddParameterBlock(10);
// cost_function.SetNumResiduals(21);
//
-// Under the hood, the implementation evaluates the cost function multiple
-// times, computing a small set of the derivatives (four by default, controlled
-// by the Stride template parameter) with each pass. There is a tradeoff with
-// the size of the passes; you may want to experiment with the stride.
+// Under the hood, the implementation evaluates the cost function
+// multiple times, computing a small set of the derivatives (four by
+// default, controlled by the Stride template parameter) with each
+// pass. There is a tradeoff with the size of the passes; you may want
+// to experiment with the stride.
#ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
#define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/dynamic_numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/dynamic_numeric_diff_cost_function.h
new file mode 100644
index 00000000000..c2bfb3223cb
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/dynamic_numeric_diff_cost_function.h
@@ -0,0 +1,265 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: mierle@gmail.com (Keir Mierle)
+// sameeragarwal@google.com (Sameer Agarwal)
+// thadh@gmail.com (Thad Hughes)
+//
+// This numeric diff implementation differs from the one found in
+// numeric_diff_cost_function.h by supporting numericdiff on cost
+// functions with variable numbers of parameters with variable
+// sizes. With the other implementation, all the sizes (both the
+// number of parameter blocks and the size of each block) must be
+// fixed at compile time.
+//
+// The functor API differs slightly from the API for fixed size
+// numeric diff; the expected interface for the cost functors is:
+//
+// struct MyCostFunctor {
+// template<typename T>
+// bool operator()(double const* const* parameters, double* residuals) const {
+// // Use parameters[i] to access the i'th parameter block.
+// }
+// }
+//
+// Since the sizing of the parameters is done at runtime, you must
+// also specify the sizes after creating the
+// DynamicNumericDiffCostFunction. For example:
+//
+// DynamicAutoDiffCostFunction<MyCostFunctor, CENTRAL> cost_function(
+// new MyCostFunctor());
+// cost_function.AddParameterBlock(5);
+// cost_function.AddParameterBlock(10);
+// cost_function.SetNumResiduals(21);
+
+#ifndef CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
+#define CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
+
+#include <cmath>
+#include <numeric>
+#include <vector>
+
+#include "ceres/cost_function.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/numeric_diff.h"
+#include "glog/logging.h"
+
+namespace ceres {
+
+template <typename CostFunctor, NumericDiffMethod method = CENTRAL>
+class DynamicNumericDiffCostFunction : public CostFunction {
+ public:
+ explicit DynamicNumericDiffCostFunction(const CostFunctor* functor,
+ Ownership ownership = TAKE_OWNERSHIP,
+ double relative_step_size = 1e-6)
+ : functor_(functor),
+ ownership_(ownership),
+ relative_step_size_(relative_step_size) {
+ }
+
+ virtual ~DynamicNumericDiffCostFunction() {
+ if (ownership_ != TAKE_OWNERSHIP) {
+ functor_.release();
+ }
+ }
+
+ void AddParameterBlock(int size) {
+ mutable_parameter_block_sizes()->push_back(size);
+ }
+
+ void SetNumResiduals(int num_residuals) {
+ set_num_residuals(num_residuals);
+ }
+
+ virtual bool Evaluate(double const* const* parameters,
+ double* residuals,
+ double** jacobians) const {
+ CHECK_GT(num_residuals(), 0)
+ << "You must call DynamicNumericDiffCostFunction::SetNumResiduals() "
+ << "before DynamicNumericDiffCostFunction::Evaluate().";
+
+ const vector<int16>& block_sizes = parameter_block_sizes();
+ CHECK(!block_sizes.empty())
+ << "You must call DynamicNumericDiffCostFunction::AddParameterBlock() "
+ << "before DynamicNumericDiffCostFunction::Evaluate().";
+
+ const bool status = EvaluateCostFunctor(parameters, residuals);
+ if (jacobians == NULL || !status) {
+ return status;
+ }
+
+ // Create local space for a copy of the parameters which will get mutated.
+ int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0);
+ vector<double> parameters_copy(parameters_size);
+ vector<double*> parameters_references_copy(block_sizes.size());
+ parameters_references_copy[0] = &parameters_copy[0];
+ for (int block = 1; block < block_sizes.size(); ++block) {
+ parameters_references_copy[block] = parameters_references_copy[block - 1]
+ + block_sizes[block - 1];
+ }
+
+ // Copy the parameters into the local temp space.
+ for (int block = 0; block < block_sizes.size(); ++block) {
+ memcpy(parameters_references_copy[block],
+ parameters[block],
+ block_sizes[block] * sizeof(*parameters[block]));
+ }
+
+ for (int block = 0; block < block_sizes.size(); ++block) {
+ if (jacobians[block] != NULL &&
+ !EvaluateJacobianForParameterBlock(block_sizes[block],
+ block,
+ relative_step_size_,
+ residuals,
+ &parameters_references_copy[0],
+ jacobians)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private:
+ bool EvaluateJacobianForParameterBlock(const int parameter_block_size,
+ const int parameter_block,
+ const double relative_step_size,
+ double const* residuals_at_eval_point,
+ double** parameters,
+ double** jacobians) const {
+ using Eigen::Map;
+ using Eigen::Matrix;
+ using Eigen::Dynamic;
+ using Eigen::RowMajor;
+
+ typedef Matrix<double, Dynamic, 1> ResidualVector;
+ typedef Matrix<double, Dynamic, 1> ParameterVector;
+ typedef Matrix<double, Dynamic, Dynamic, RowMajor> JacobianMatrix;
+
+ int num_residuals = this->num_residuals();
+
+ Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block],
+ num_residuals,
+ parameter_block_size);
+
+ // Mutate one element at a time and then restore.
+ Map<ParameterVector> x_plus_delta(parameters[parameter_block],
+ parameter_block_size);
+ ParameterVector x(x_plus_delta);
+ ParameterVector step_size = x.array().abs() * relative_step_size;
+
+ // To handle cases where a paremeter is exactly zero, instead use
+ // the mean step_size for the other dimensions.
+ double fallback_step_size = step_size.sum() / step_size.rows();
+ if (fallback_step_size == 0.0) {
+ // If all the parameters are zero, there's no good answer. Use the given
+ // relative step_size as absolute step_size and hope for the best.
+ fallback_step_size = relative_step_size;
+ }
+
+ // For each parameter in the parameter block, use finite
+ // differences to compute the derivative for that parameter.
+ for (int j = 0; j < parameter_block_size; ++j) {
+ if (step_size(j) == 0.0) {
+ // The parameter is exactly zero, so compromise and use the
+ // mean step_size from the other parameters. This can break in
+ // many cases, but it's hard to pick a good number without
+ // problem specific knowledge.
+ step_size(j) = fallback_step_size;
+ }
+ x_plus_delta(j) = x(j) + step_size(j);
+
+ ResidualVector residuals(num_residuals);
+ if (!EvaluateCostFunctor(parameters, &residuals[0])) {
+ // Something went wrong; bail.
+ return false;
+ }
+
+ // Compute this column of the jacobian in 3 steps:
+ // 1. Store residuals for the forward part.
+ // 2. Subtract residuals for the backward (or 0) part.
+ // 3. Divide out the run.
+ parameter_jacobian.col(j).matrix() = residuals;
+
+ double one_over_h = 1 / step_size(j);
+ if (method == CENTRAL) {
+ // Compute the function on the other side of x(j).
+ x_plus_delta(j) = x(j) - step_size(j);
+
+ if (!EvaluateCostFunctor(parameters, &residuals[0])) {
+ // Something went wrong; bail.
+ return false;
+ }
+
+ parameter_jacobian.col(j) -= residuals;
+ one_over_h /= 2;
+ } else {
+ // Forward difference only; reuse existing residuals evaluation.
+ parameter_jacobian.col(j) -=
+ Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
+ }
+ x_plus_delta(j) = x(j); // Restore x_plus_delta.
+
+ // Divide out the run to get slope.
+ parameter_jacobian.col(j) *= one_over_h;
+ }
+ return true;
+ }
+
+ bool EvaluateCostFunctor(double const* const* parameters,
+ double* residuals) const {
+ return EvaluateCostFunctorImpl(functor_.get(),
+ parameters,
+ residuals,
+ functor_.get());
+ }
+
+ // Helper templates to allow evaluation of a functor or a
+ // CostFunction.
+ bool EvaluateCostFunctorImpl(const CostFunctor* functor,
+ double const* const* parameters,
+ double* residuals,
+ const void* /* NOT USED */) const {
+ return (*functor)(parameters, residuals);
+ }
+
+ bool EvaluateCostFunctorImpl(const CostFunctor* functor,
+ double const* const* parameters,
+ double* residuals,
+ const CostFunction* /* NOT USED */) const {
+ return functor->Evaluate(parameters, residuals, NULL);
+ }
+
+ internal::scoped_ptr<const CostFunctor> functor_;
+ Ownership ownership_;
+ const double relative_step_size_;
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
index cf21d7a5001..3a96625e3fd 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
@@ -172,7 +172,7 @@ inline void Make1stOrderPerturbation(int offset, const T* src, JetT* dst) {
for (int j = 0; j < N; ++j) {
dst[j].a = src[j];
dst[j].v.setZero();
- dst[j].v[offset + j] = 1.0;
+ dst[j].v[offset + j] = T(1.0);
}
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
index ee264d1619d..694070b228c 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
@@ -113,7 +113,6 @@ class FixedArray {
// REQUIRES: 0 <= i < size()
// Returns a reference to the "i"th element.
inline T& operator[](size_type i) {
- DCHECK_GE(i, 0);
DCHECK_LT(i, size_);
return array_[i].element;
}
@@ -121,7 +120,6 @@ class FixedArray {
// REQUIRES: 0 <= i < size()
// Returns a reference to the "i"th element.
inline const T& operator[](size_type i) const {
- DCHECK_GE(i, 0);
DCHECK_LT(i, size_);
return array_[i].element;
}
@@ -168,8 +166,6 @@ inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
array_((n <= kInlineElements
? reinterpret_cast<InnerContainer*>(inline_space_)
: new InnerContainer[n])) {
- DCHECK_GE(n, size_t(0));
-
// Construct only the elements actually used.
if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
for (size_t i = 0; i != size_; ++i) {
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
index 388cf30fe70..1ed55be6e03 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
@@ -145,12 +145,11 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
//
// Sprocket* AllocateSprocket() MUST_USE_RESULT;
//
-#undef MUST_USE_RESULT
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
&& !defined(COMPILER_ICC)
-#define MUST_USE_RESULT __attribute__ ((warn_unused_result))
+#define CERES_MUST_USE_RESULT __attribute__ ((warn_unused_result))
#else
-#define MUST_USE_RESULT
+#define CERES_MUST_USE_RESULT
#endif
// Platform independent macros to get aligned memory allocations.
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h
index 4058366c4a1..5048348564a 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h
@@ -90,6 +90,7 @@ struct NumericDiff {
const CostFunctor* functor,
double const* residuals_at_eval_point,
const double relative_step_size,
+ int num_residuals,
double **parameters,
double *jacobian) {
using Eigen::Map;
@@ -97,15 +98,21 @@ struct NumericDiff {
using Eigen::RowMajor;
using Eigen::ColMajor;
+ const int NUM_RESIDUALS =
+ (kNumResiduals != ceres::DYNAMIC ? kNumResiduals : num_residuals);
+
typedef Matrix<double, kNumResiduals, 1> ResidualVector;
typedef Matrix<double, kParameterBlockSize, 1> ParameterVector;
- typedef Matrix<double, kNumResiduals, kParameterBlockSize,
+ typedef Matrix<double,
+ kNumResiduals,
+ kParameterBlockSize,
(kParameterBlockSize == 1 &&
- kNumResiduals > 1) ? ColMajor : RowMajor> JacobianMatrix;
+ kNumResiduals > 1) ? ColMajor : RowMajor>
+ JacobianMatrix;
Map<JacobianMatrix> parameter_jacobian(jacobian,
- kNumResiduals,
+ NUM_RESIDUALS,
kParameterBlockSize);
// Mutate 1 element at a time and then restore.
@@ -125,16 +132,16 @@ struct NumericDiff {
// For each parameter in the parameter block, use finite differences to
// compute the derivative for that parameter.
+
+ ResidualVector residuals(NUM_RESIDUALS);
for (int j = 0; j < kParameterBlockSize; ++j) {
const double delta =
(step_size(j) == 0.0) ? fallback_step_size : step_size(j);
x_plus_delta(j) = x(j) + delta;
- double residuals[kNumResiduals]; // NOLINT
-
if (!EvaluateImpl<CostFunctor, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>(
- functor, parameters, residuals, functor)) {
+ functor, parameters, residuals.data(), functor)) {
return false;
}
@@ -142,8 +149,7 @@ struct NumericDiff {
// 1. Store residuals for the forward part.
// 2. Subtract residuals for the backward (or 0) part.
// 3. Divide out the run.
- parameter_jacobian.col(j) =
- Map<const ResidualVector>(residuals, kNumResiduals);
+ parameter_jacobian.col(j) = residuals;
double one_over_delta = 1.0 / delta;
if (kMethod == CENTRAL) {
@@ -151,17 +157,16 @@ struct NumericDiff {
x_plus_delta(j) = x(j) - delta;
if (!EvaluateImpl<CostFunctor, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>(
- functor, parameters, residuals, functor)) {
+ functor, parameters, residuals.data(), functor)) {
return false;
}
- parameter_jacobian.col(j) -=
- Map<ResidualVector>(residuals, kNumResiduals, 1);
+ parameter_jacobian.col(j) -= residuals;
one_over_delta /= 2;
} else {
// Forward difference only; reuse existing residuals evaluation.
parameter_jacobian.col(j) -=
- Map<const ResidualVector>(residuals_at_eval_point, kNumResiduals);
+ Map<const ResidualVector>(residuals_at_eval_point, NUM_RESIDUALS);
}
x_plus_delta(j) = x(j); // Restore x_plus_delta.
@@ -186,6 +191,7 @@ struct NumericDiff<CostFunctor, kMethod, kNumResiduals,
const CostFunctor* functor,
double const* residuals_at_eval_point,
const double relative_step_size,
+ const int num_residuals,
double **parameters,
double *jacobian) {
LOG(FATAL) << "Control should never reach here.";
diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
index 987c2d91f79..56892562556 100644
--- a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
+++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
@@ -50,6 +50,7 @@ struct IterationSummary {
cost(0.0),
cost_change(0.0),
gradient_max_norm(0.0),
+ gradient_norm(0.0),
step_norm(0.0),
eta(0.0),
step_size(0.0),
@@ -100,6 +101,9 @@ struct IterationSummary {
// Infinity norm of the gradient vector.
double gradient_max_norm;
+ // 2-norm of the gradient vector.
+ double gradient_norm;
+
// 2-norm of the size of the step computed by the optimization
// algorithm.
double step_norm;
diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h
index 4d2a857dc3d..55caa05dbac 100644
--- a/extern/libmv/third_party/ceres/include/ceres/jet.h
+++ b/extern/libmv/third_party/ceres/include/ceres/jet.h
@@ -106,8 +106,8 @@
// Jet<double, 2> y(1); // Pick the 1st dual number for y.
// Jet<double, 2> z = f(x, y);
//
-// LG << "df/dx = " << z.a[0]
-// << "df/dy = " << z.a[1];
+// LOG(INFO) << "df/dx = " << z.a[0]
+// << "df/dy = " << z.a[1];
//
// Most users should not use Jet objects directly; a wrapper around Jet objects,
// which makes computing the derivative, gradient, or jacobian of templated
@@ -192,6 +192,17 @@ struct Jet {
v[k] = T(1.0);
}
+ // Constructor from scalar and vector part
+ // The use of Eigen::DenseBase allows Eigen expressions
+ // to be passed in without being fully evaluated until
+ // they are assigned to v
+ template<typename Derived>
+ Jet(const T& value, const Eigen::DenseBase<Derived> &vIn)
+ : a(value),
+ v(vIn)
+ {
+ }
+
// Compound operators
Jet<T, N>& operator+=(const Jet<T, N> &y) {
*this = *this + y;
@@ -246,101 +257,70 @@ Jet<T, N> const& operator+(const Jet<T, N>& f) {
// Unary -
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>&f) {
- Jet<T, N> g;
- g.a = -f.a;
- g.v = -f.v;
- return g;
+ return Jet<T, N>(-f.a, -f.v);
}
// Binary +
template<typename T, int N> inline
Jet<T, N> operator+(const Jet<T, N>& f,
const Jet<T, N>& g) {
- Jet<T, N> h;
- h.a = f.a + g.a;
- h.v = f.v + g.v;
- return h;
+ return Jet<T, N>(f.a + g.a, f.v + g.v);
}
// Binary + with a scalar: x + s
template<typename T, int N> inline
Jet<T, N> operator+(const Jet<T, N>& f, T s) {
- Jet<T, N> h;
- h.a = f.a + s;
- h.v = f.v;
- return h;
+ return Jet<T, N>(f.a + s, f.v);
}
// Binary + with a scalar: s + x
template<typename T, int N> inline
Jet<T, N> operator+(T s, const Jet<T, N>& f) {
- Jet<T, N> h;
- h.a = f.a + s;
- h.v = f.v;
- return h;
+ return Jet<T, N>(f.a + s, f.v);
}
// Binary -
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>& f,
const Jet<T, N>& g) {
- Jet<T, N> h;
- h.a = f.a - g.a;
- h.v = f.v - g.v;
- return h;
+ return Jet<T, N>(f.a - g.a, f.v - g.v);
}
// Binary - with a scalar: x - s
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>& f, T s) {
- Jet<T, N> h;
- h.a = f.a - s;
- h.v = f.v;
- return h;
+ return Jet<T, N>(f.a - s, f.v);
}
// Binary - with a scalar: s - x
template<typename T, int N> inline
Jet<T, N> operator-(T s, const Jet<T, N>& f) {
- Jet<T, N> h;
- h.a = s - f.a;
- h.v = -f.v;
- return h;
+ return Jet<T, N>(s - f.a, -f.v);
}
// Binary *
template<typename T, int N> inline
Jet<T, N> operator*(const Jet<T, N>& f,
const Jet<T, N>& g) {
- Jet<T, N> h;
- h.a = f.a * g.a;
- h.v = f.a * g.v + f.v * g.a;
- return h;
+ return Jet<T, N>(f.a * g.a, f.a * g.v + f.v * g.a);
}
// Binary * with a scalar: x * s
template<typename T, int N> inline
Jet<T, N> operator*(const Jet<T, N>& f, T s) {
- Jet<T, N> h;
- h.a = f.a * s;
- h.v = f.v * s;
- return h;
+ return Jet<T, N>(f.a * s, f.v * s);
}
// Binary * with a scalar: s * x
template<typename T, int N> inline
Jet<T, N> operator*(T s, const Jet<T, N>& f) {
- Jet<T, N> h;
- h.a = f.a * s;
- h.v = f.v * s;
- return h;
+ return Jet<T, N>(f.a * s, f.v * s);
}
// Binary /
template<typename T, int N> inline
Jet<T, N> operator/(const Jet<T, N>& f,
const Jet<T, N>& g) {
- Jet<T, N> h;
// This uses:
//
// a + u (a + u)(b - v) (a + u)(b - v)
@@ -349,32 +329,22 @@ Jet<T, N> operator/(const Jet<T, N>& f,
//
// which holds because v*v = 0.
const T g_a_inverse = T(1.0) / g.a;
- h.a = f.a * g_a_inverse;
const T f_a_by_g_a = f.a * g_a_inverse;
- for (int i = 0; i < N; ++i) {
- h.v[i] = (f.v[i] - f_a_by_g_a * g.v[i]) * g_a_inverse;
- }
- return h;
+ return Jet<T, N>(f.a * g_a_inverse, (f.v - f_a_by_g_a * g.v) * g_a_inverse);
}
// Binary / with a scalar: s / x
template<typename T, int N> inline
Jet<T, N> operator/(T s, const Jet<T, N>& g) {
- Jet<T, N> h;
- h.a = s / g.a;
const T minus_s_g_a_inverse2 = -s / (g.a * g.a);
- h.v = g.v * minus_s_g_a_inverse2;
- return h;
+ return Jet<T, N>(s / g.a, g.v * minus_s_g_a_inverse2);
}
// Binary / with a scalar: x / s
template<typename T, int N> inline
Jet<T, N> operator/(const Jet<T, N>& f, T s) {
- Jet<T, N> h;
const T s_inverse = 1.0 / s;
- h.a = f.a * s_inverse;
- h.v = f.v * s_inverse;
- return h;
+ return Jet<T, N>(f.a * s_inverse, f.v * s_inverse);
}
// Binary comparison operators for both scalars and jets.
@@ -433,122 +403,84 @@ Jet<T, N> abs(const Jet<T, N>& f) {
// log(a + h) ~= log(a) + h / a
template <typename T, int N> inline
Jet<T, N> log(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = log(f.a);
const T a_inverse = T(1.0) / f.a;
- g.v = f.v * a_inverse;
- return g;
+ return Jet<T, N>(log(f.a), f.v * a_inverse);
}
// exp(a + h) ~= exp(a) + exp(a) h
template <typename T, int N> inline
Jet<T, N> exp(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = exp(f.a);
- g.v = g.a * f.v;
- return g;
+ const T tmp = exp(f.a);
+ return Jet<T, N>(tmp, tmp * f.v);
}
// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a))
template <typename T, int N> inline
Jet<T, N> sqrt(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = sqrt(f.a);
- const T two_a_inverse = T(1.0) / (T(2.0) * g.a);
- g.v = f.v * two_a_inverse;
- return g;
+ const T tmp = sqrt(f.a);
+ const T two_a_inverse = T(1.0) / (T(2.0) * tmp);
+ return Jet<T, N>(tmp, f.v * two_a_inverse);
}
// cos(a + h) ~= cos(a) - sin(a) h
template <typename T, int N> inline
Jet<T, N> cos(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = cos(f.a);
- const T sin_a = sin(f.a);
- g.v = - sin_a * f.v;
- return g;
+ return Jet<T, N>(cos(f.a), - sin(f.a) * f.v);
}
// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
template <typename T, int N> inline
Jet<T, N> acos(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = acos(f.a);
const T tmp = - T(1.0) / sqrt(T(1.0) - f.a * f.a);
- g.v = tmp * f.v;
- return g;
+ return Jet<T, N>(acos(f.a), tmp * f.v);
}
// sin(a + h) ~= sin(a) + cos(a) h
template <typename T, int N> inline
Jet<T, N> sin(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = sin(f.a);
- const T cos_a = cos(f.a);
- g.v = cos_a * f.v;
- return g;
+ return Jet<T, N>(sin(f.a), cos(f.a) * f.v);
}
// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h
template <typename T, int N> inline
Jet<T, N> asin(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = asin(f.a);
const T tmp = T(1.0) / sqrt(T(1.0) - f.a * f.a);
- g.v = tmp * f.v;
- return g;
+ return Jet<T, N>(asin(f.a), tmp * f.v);
}
// tan(a + h) ~= tan(a) + (1 + tan(a)^2) h
template <typename T, int N> inline
Jet<T, N> tan(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = tan(f.a);
- double tan_a = tan(f.a);
+ const T tan_a = tan(f.a);
const T tmp = T(1.0) + tan_a * tan_a;
- g.v = tmp * f.v;
- return g;
+ return Jet<T, N>(tan_a, tmp * f.v);
}
// atan(a + h) ~= atan(a) + 1 / (1 + a^2) h
template <typename T, int N> inline
Jet<T, N> atan(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = atan(f.a);
const T tmp = T(1.0) / (T(1.0) + f.a * f.a);
- g.v = tmp * f.v;
- return g;
+ return Jet<T, N>(atan(f.a), tmp * f.v);
}
// sinh(a + h) ~= sinh(a) + cosh(a) h
template <typename T, int N> inline
Jet<T, N> sinh(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = sinh(f.a);
- const T cosh_a = cosh(f.a);
- g.v = cosh_a * f.v;
- return g;
+ return Jet<T, N>(sinh(f.a), cosh(f.a) * f.v);
}
// cosh(a + h) ~= cosh(a) + sinh(a) h
template <typename T, int N> inline
Jet<T, N> cosh(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = cosh(f.a);
- const T sinh_a = sinh(f.a);
- g.v = sinh_a * f.v;
- return g;
+ return Jet<T, N>(cosh(f.a), sinh(f.a) * f.v);
}
// tanh(a + h) ~= tanh(a) + (1 - tanh(a)^2) h
template <typename T, int N> inline
Jet<T, N> tanh(const Jet<T, N>& f) {
- Jet<T, N> g;
- g.a = tanh(f.a);
- double tanh_a = tanh(f.a);
+ const T tanh_a = tanh(f.a);
const T tmp = T(1.0) - tanh_a * tanh_a;
- g.v = tmp * f.v;
- return g;
+ return Jet<T, N>(tanh_a, tmp * f.v);
}
// Jet Classification. It is not clear what the appropriate semantics are for
@@ -628,36 +560,25 @@ Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
// f = a + da
// g = b + db
- Jet<T, N> out;
-
- out.a = atan2(g.a, f.a);
-
- T const temp = T(1.0) / (f.a * f.a + g.a * g.a);
- out.v = temp * (- g.a * f.v + f.a * g.v);
- return out;
+ T const tmp = T(1.0) / (f.a * f.a + g.a * g.a);
+ return Jet<T, N>(atan2(g.a, f.a), tmp * (- g.a * f.v + f.a * g.v));
}
-// pow -- base is a differentiatble function, exponent is a constant.
+// pow -- base is a differentiable function, exponent is a constant.
// (a+da)^p ~= a^p + p*a^(p-1) da
template <typename T, int N> inline
Jet<T, N> pow(const Jet<T, N>& f, double g) {
- Jet<T, N> out;
- out.a = pow(f.a, g);
- T const temp = g * pow(f.a, g - T(1.0));
- out.v = temp * f.v;
- return out;
+ T const tmp = g * pow(f.a, g - T(1.0));
+ return Jet<T, N>(pow(f.a, g), tmp * f.v);
}
// pow -- base is a constant, exponent is a differentiable function.
// (a)^(p+dp) ~= a^p + a^p log(a) dp
template <typename T, int N> inline
Jet<T, N> pow(double f, const Jet<T, N>& g) {
- Jet<T, N> out;
- out.a = pow(f, g.a);
- T const temp = log(f) * out.a;
- out.v = temp * g.v;
- return out;
+ T const tmp = pow(f, g.a);
+ return Jet<T, N>(tmp, log(f) * tmp * g.v);
}
@@ -665,15 +586,11 @@ Jet<T, N> pow(double f, const Jet<T, N>& g) {
// (a+da)^(b+db) ~= a^b + b * a^(b-1) da + a^b log(a) * db
template <typename T, int N> inline
Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) {
- Jet<T, N> out;
-
- T const temp1 = pow(f.a, g.a);
- T const temp2 = g.a * pow(f.a, g.a - T(1.0));
- T const temp3 = temp1 * log(f.a);
+ T const tmp1 = pow(f.a, g.a);
+ T const tmp2 = g.a * pow(f.a, g.a - T(1.0));
+ T const tmp3 = tmp1 * log(f.a);
- out.a = temp1;
- out.v = temp2 * f.v + temp3 * g.v;
- return out;
+ return Jet<T, N>(tmp1, tmp2 * f.v + tmp3 * g.v);
}
// Define the helper functions Eigen needs to embed Jet types.
@@ -740,7 +657,8 @@ struct NumTraits<ceres::Jet<T, N> > {
AddCost = 1,
// For Jet types, multiplication is more expensive than addition.
MulCost = 3,
- HasFloatingPoint = 1
+ HasFloatingPoint = 1,
+ RequireInitialization = 1
};
};
diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
index a47a66d9672..de6b74ad552 100644
--- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
@@ -95,6 +95,21 @@
// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing
// a 1-dimensional output from two arguments, both 2-dimensional.
//
+// NumericDiffCostFunction also supports cost functions with a
+// runtime-determined number of residuals. For example:
+//
+// CostFunction* cost_function
+// = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, DYNAMIC, 2, 2>(
+// new CostFunctorWithDynamicNumResiduals(1.0), ^ ^ ^
+// TAKE_OWNERSHIP, | | |
+// runtime_number_of_residuals); <----+ | | |
+// | | | |
+// | | | |
+// Actual number of residuals ------+ | | |
+// Indicate dynamic number of residuals --------------------+ | |
+// Dimension of x ------------------------------------------------+ |
+// Dimension of y ---------------------------------------------------+
+//
// The framework can currently accommodate cost functions of up to 10
// independent variables, and there is no limit on the dimensionality
// of each of them.
@@ -104,8 +119,6 @@
// central differences begin with, and only after that works, trying forward
// difference to improve performance.
//
-// TODO(sameeragarwal): Add support for dynamic number of residuals.
-//
// WARNING #1: A common beginner's error when first using
// NumericDiffCostFunction is to get the sizing wrong. In particular,
// there is a tendency to set the template parameters to (dimension of
@@ -177,17 +190,19 @@ class NumericDiffCostFunction
N5, N6, N7, N8, N9> {
public:
NumericDiffCostFunction(CostFunctor* functor,
+ Ownership ownership = TAKE_OWNERSHIP,
+ int num_residuals = kNumResiduals,
const double relative_step_size = 1e-6)
:functor_(functor),
- ownership_(TAKE_OWNERSHIP),
- relative_step_size_(relative_step_size) {}
-
- NumericDiffCostFunction(CostFunctor* functor,
- Ownership ownership,
- const double relative_step_size = 1e-6)
- : functor_(functor),
- ownership_(ownership),
- relative_step_size_(relative_step_size) {}
+ ownership_(ownership),
+ relative_step_size_(relative_step_size) {
+ if (kNumResiduals == DYNAMIC) {
+ SizedCostFunction<kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9>
+ ::set_num_residuals(num_residuals);
+ }
+ }
~NumericDiffCostFunction() {
if (ownership_ != TAKE_OWNERSHIP) {
@@ -216,7 +231,7 @@ class NumericDiffCostFunction
return false;
}
- if (!jacobians) {
+ if (jacobians == NULL) {
return true;
}
@@ -264,6 +279,9 @@ class NumericDiffCostFunction
functor_.get(), \
residuals, \
relative_step_size_, \
+ SizedCostFunction<kNumResiduals, \
+ N0, N1, N2, N3, N4, \
+ N5, N6, N7, N8, N9>::num_residuals(), \
parameters_reference_copy.get(), \
jacobians[block])) { \
return false; \
diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h
index 039e1a17aa7..a29eb97fa6e 100644
--- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h
+++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h
@@ -124,6 +124,8 @@ class NumericDiffFunctor {
kNumResiduals,
N0, N1, N2, N3, N4,
N5, N6, N7, N8, N9>(new Functor,
+ TAKE_OWNERSHIP,
+ kNumResiduals,
relative_step_size)) {
}
@@ -133,7 +135,10 @@ class NumericDiffFunctor {
kNumResiduals,
N0, N1, N2, N3, N4,
N5, N6, N7, N8, N9>(
- functor, relative_step_size)) {
+ functor,
+ TAKE_OWNERSHIP,
+ kNumResiduals,
+ relative_step_size)) {
}
bool operator()(const double* x0, double* residuals) const {
diff --git a/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h
index e373d35b9d7..dff859d7b82 100644
--- a/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h
+++ b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h
@@ -84,11 +84,8 @@ class OrderedGroups {
element_to_group_.clear();
}
- // Remove the element, no matter what group it is in. If the element
- // is not a member of any group, calling this method will result in
- // a crash.
- //
- // Return value indicates if the element was actually removed.
+ // Remove the element, no matter what group it is in. Return value
+ // indicates if the element was actually removed.
bool Remove(const T element) {
const int current_group = GroupId(element);
if (current_group < 0) {
diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h
index 663616ddb3b..cd433f9c5b2 100644
--- a/extern/libmv/third_party/ceres/include/ceres/problem.h
+++ b/extern/libmv/third_party/ceres/include/ceres/problem.h
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -341,6 +341,26 @@ class Problem {
// parameter_block.size() == NumParameterBlocks.
void GetParameterBlocks(vector<double*>* parameter_blocks) const;
+ // Fills the passed residual_blocks vector with pointers to the
+ // residual blocks currently in the problem. After this call,
+ // residual_blocks.size() == NumResidualBlocks.
+ void GetResidualBlocks(vector<ResidualBlockId>* residual_blocks) const;
+
+ // Get all the parameter blocks that depend on the given residual block.
+ void GetParameterBlocksForResidualBlock(
+ const ResidualBlockId residual_block,
+ vector<double*>* parameter_blocks) const;
+
+ // Get all the residual blocks that depend on the given parameter block.
+ //
+ // If Problem::Options::enable_fast_parameter_block_removal is true, then
+ // getting the residual blocks is fast and depends only on the number of
+ // residual blocks. Otherwise, getting the residual blocks for a parameter
+ // block will incur a scan of the entire Problem object.
+ void GetResidualBlocksForParameterBlock(
+ const double* values,
+ vector<ResidualBlockId>* residual_blocks) const;
+
// Options struct to control Problem::Evaluate.
struct EvaluateOptions {
EvaluateOptions()
diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h
index ea0b76947eb..e3dbfe84a5a 100644
--- a/extern/libmv/third_party/ceres/include/ceres/rotation.h
+++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h
@@ -395,7 +395,7 @@ void AngleAxisToRotationMatrix(
const MatrixAdapter<T, row_stride, col_stride>& R) {
static const T kOne = T(1.0);
const T theta2 = DotProduct(angle_axis, angle_axis);
- if (theta2 > 0.0) {
+ if (theta2 > T(std::numeric_limits<double>::epsilon())) {
// We want to be careful to only evaluate the square root if the
// norm of the angle_axis vector is greater than zero. Otherwise
// we get a division by zero.
@@ -417,15 +417,15 @@ void AngleAxisToRotationMatrix(
R(1, 2) = -wx*sintheta + wy*wz*(kOne - costheta);
R(2, 2) = costheta + wz*wz*(kOne - costheta);
} else {
- // At zero, we switch to using the first order Taylor expansion.
+ // Near zero, we switch to using the first order Taylor expansion.
R(0, 0) = kOne;
- R(1, 0) = -angle_axis[2];
- R(2, 0) = angle_axis[1];
- R(0, 1) = angle_axis[2];
+ R(1, 0) = angle_axis[2];
+ R(2, 0) = -angle_axis[1];
+ R(0, 1) = -angle_axis[2];
R(1, 1) = kOne;
- R(2, 1) = -angle_axis[0];
- R(0, 2) = -angle_axis[1];
- R(1, 2) = angle_axis[0];
+ R(2, 1) = angle_axis[0];
+ R(0, 2) = angle_axis[1];
+ R(1, 2) = -angle_axis[0];
R(2, 2) = kOne;
}
}
@@ -580,12 +580,8 @@ T DotProduct(const T x[3], const T y[3]) {
template<typename T> inline
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
- T w[3];
- T sintheta;
- T costheta;
-
const T theta2 = DotProduct(angle_axis, angle_axis);
- if (theta2 > 0.0) {
+ if (theta2 > T(std::numeric_limits<double>::epsilon())) {
// Away from zero, use the rodriguez formula
//
// result = pt costheta +
@@ -597,19 +593,25 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
// we get a division by zero.
//
const T theta = sqrt(theta2);
- w[0] = angle_axis[0] / theta;
- w[1] = angle_axis[1] / theta;
- w[2] = angle_axis[2] / theta;
- costheta = cos(theta);
- sintheta = sin(theta);
- T w_cross_pt[3];
- CrossProduct(w, pt, w_cross_pt);
- T w_dot_pt = DotProduct(w, pt);
- for (int i = 0; i < 3; ++i) {
- result[i] = pt[i] * costheta +
- w_cross_pt[i] * sintheta +
- w[i] * (T(1.0) - costheta) * w_dot_pt;
- }
+ const T costheta = cos(theta);
+ const T sintheta = sin(theta);
+ const T theta_inverse = 1.0 / theta;
+
+ const T w[3] = { angle_axis[0] * theta_inverse,
+ angle_axis[1] * theta_inverse,
+ angle_axis[2] * theta_inverse };
+
+ // Explicitly inlined evaluation of the cross product for
+ // performance reasons.
+ const T w_cross_pt[3] = { w[1] * pt[2] - w[2] * pt[1],
+ w[2] * pt[0] - w[0] * pt[2],
+ w[0] * pt[1] - w[1] * pt[0] };
+ const T tmp =
+ (w[0] * pt[0] + w[1] * pt[1] + w[2] * pt[2]) * (T(1.0) - costheta);
+
+ result[0] = pt[0] * costheta + w_cross_pt[0] * sintheta + w[0] * tmp;
+ result[1] = pt[1] * costheta + w_cross_pt[1] * sintheta + w[1] * tmp;
+ result[2] = pt[2] * costheta + w_cross_pt[2] * sintheta + w[2] * tmp;
} else {
// Near zero, the first order Taylor approximation of the rotation
// matrix R corresponding to a vector w and angle w is
@@ -623,13 +625,18 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
// and actually performing multiplication with the point pt, gives us
// R * pt = pt + w x pt.
//
- // Switching to the Taylor expansion at zero helps avoid all sorts
- // of numerical nastiness.
- T w_cross_pt[3];
- CrossProduct(angle_axis, pt, w_cross_pt);
- for (int i = 0; i < 3; ++i) {
- result[i] = pt[i] + w_cross_pt[i];
- }
+ // Switching to the Taylor expansion near zero provides meaningful
+ // derivatives when evaluated using Jets.
+ //
+ // Explicitly inlined evaluation of the cross product for
+ // performance reasons.
+ const T w_cross_pt[3] = { angle_axis[1] * pt[2] - angle_axis[2] * pt[1],
+ angle_axis[2] * pt[0] - angle_axis[0] * pt[2],
+ angle_axis[0] * pt[1] - angle_axis[1] * pt[0] };
+
+ result[0] = pt[0] + w_cross_pt[0];
+ result[1] = pt[1] + w_cross_pt[1];
+ result[2] = pt[2] + w_cross_pt[2];
}
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h
index 25b762a7bd5..7776c470eba 100644
--- a/extern/libmv/third_party/ceres/include/ceres/solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/solver.h
@@ -98,7 +98,7 @@ class Solver {
#endif
preconditioner_type = JACOBI;
-
+ visibility_clustering_type = CANONICAL_VIEWS;
dense_linear_algebra_library_type = EIGEN;
sparse_linear_algebra_library_type = SUITE_SPARSE;
#if defined(CERES_NO_SUITESPARSE) && !defined(CERES_NO_CXSPARSE)
@@ -385,6 +385,11 @@ class Solver {
// Type of preconditioner to use with the iterative linear solvers.
PreconditionerType preconditioner_type;
+ // Type of clustering algorithm to use for visibility based
+ // preconditioning. This option is used only when the
+ // preconditioner_type is CLUSTER_JACOBI or CLUSTER_TRIDIAGONAL.
+ VisibilityClusteringType visibility_clustering_type;
+
// Ceres supports using multiple dense linear algebra libraries
// for dense matrix factorizations. Currently EIGEN and LAPACK are
// the valid choices. EIGEN is always available, LAPACK refers to
@@ -718,9 +723,12 @@ class Solver {
// description of the error.
string error;
- // Cost of the problem before and after the optimization. See
- // problem.h for definition of the cost of a problem.
+ // Cost of the problem (value of the objective function) before
+ // the optimization.
double initial_cost;
+
+ // Cost of the problem (value of the objective function) after the
+ // optimization.
double final_cost;
// The part of the total cost that comes from residual blocks that
@@ -728,10 +736,21 @@ class Solver {
// blocks that they depend on were fixed.
double fixed_cost;
+ // IterationSummary for each minimizer iteration in order.
vector<IterationSummary> iterations;
+ // Number of minimizer iterations in which the step was
+ // accepted. Unless use_non_monotonic_steps is true this is also
+ // the number of steps in which the objective function value/cost
+ // went down.
int num_successful_steps;
+
+ // Number of minimizer iterations in which the step was rejected
+ // either because it did not reduce the cost enough or the step
+ // was not numerically valid.
int num_unsuccessful_steps;
+
+ // Number of times inner iterations were performed.
int num_inner_iteration_steps;
// All times reported below are wall times.
@@ -753,58 +772,160 @@ class Solver {
// Some total of all time spent inside Ceres when Solve is called.
double total_time_in_seconds;
+ // Time (in seconds) spent in the linear solver computing the
+ // trust region step.
double linear_solver_time_in_seconds;
+
+ // Time (in seconds) spent evaluating the residual vector.
double residual_evaluation_time_in_seconds;
+
+ // Time (in seconds) spent evaluating the jacobian matrix.
double jacobian_evaluation_time_in_seconds;
+
+ // Time (in seconds) spent doing inner iterations.
double inner_iteration_time_in_seconds;
- // Preprocessor summary.
+ // Number of parameter blocks in the problem.
int num_parameter_blocks;
+
+ // Number of parameters in the probem.
int num_parameters;
+
+ // Dimension of the tangent space of the problem (or the number of
+ // columns in the Jacobian for the problem). This is different
+ // from num_parameters if a parameter block is associated with a
+ // LocalParameterization
int num_effective_parameters;
+
+ // Number of residual blocks in the problem.
int num_residual_blocks;
+
+ // Number of residuals in the problem.
int num_residuals;
+ // Number of parameter blocks in the problem after the inactive
+ // and constant parameter blocks have been removed. A parameter
+ // block is inactive if no residual block refers to it.
int num_parameter_blocks_reduced;
+
+ // Number of parameters in the reduced problem.
int num_parameters_reduced;
+
+ // Dimension of the tangent space of the reduced problem (or the
+ // number of columns in the Jacobian for the reduced
+ // problem). This is different from num_parameters_reduced if a
+ // parameter block in the reduced problem is associated with a
+ // LocalParameterization.
int num_effective_parameters_reduced;
+
+ // Number of residual blocks in the reduced problem.
int num_residual_blocks_reduced;
- int num_residuals_reduced;
- int num_eliminate_blocks_given;
- int num_eliminate_blocks_used;
+ // Number of residuals in the reduced problem.
+ int num_residuals_reduced;
+ // Number of threads specified by the user for Jacobian and
+ // residual evaluation.
int num_threads_given;
+
+ // Number of threads actually used by the solver for Jacobian and
+ // residual evaluation. This number is not equal to
+ // num_threads_given if OpenMP is not available.
int num_threads_used;
+ // Number of threads specified by the user for solving the trust
+ // region problem.
int num_linear_solver_threads_given;
+
+ // Number of threads actually used by the solver for solving the
+ // trust region problem. This number is not equal to
+ // num_threads_given if OpenMP is not available.
int num_linear_solver_threads_used;
+ // Type of the linear solver requested by the user.
LinearSolverType linear_solver_type_given;
+
+ // Type of the linear solver actually used. This may be different
+ // from linear_solver_type_given if Ceres determines that the
+ // problem structure is not compatible with the linear solver
+ // requested or if the linear solver requested by the user is not
+ // available, e.g. The user requested SPARSE_NORMAL_CHOLESKY but
+ // no sparse linear algebra library was available.
LinearSolverType linear_solver_type_used;
+ // Size of the elimination groups given by the user as hints to
+ // the linear solver.
vector<int> linear_solver_ordering_given;
+
+ // Size of the parameter groups used by the solver when ordering
+ // the columns of the Jacobian. This maybe different from
+ // linear_solver_ordering_given if the user left
+ // linear_solver_ordering_given blank and asked for an automatic
+ // ordering, or if the problem contains some constant or inactive
+ // parameter blocks.
vector<int> linear_solver_ordering_used;
+ // True if the user asked for inner iterations to be used as part
+ // of the optimization.
bool inner_iterations_given;
+
+ // True if the user asked for inner iterations to be used as part
+ // of the optimization and the problem structure was such that
+ // they were actually performed. e.g., in a problem with just one
+ // parameter block, inner iterations are not performed.
bool inner_iterations_used;
+ // Size of the parameter groups given by the user for performing
+ // inner iterations.
vector<int> inner_iteration_ordering_given;
+
+ // Size of the parameter groups given used by the solver for
+ // performing inner iterations. This maybe different from
+ // inner_iteration_ordering_given if the user left
+ // inner_iteration_ordering_given blank and asked for an automatic
+ // ordering, or if the problem contains some constant or inactive
+ // parameter blocks.
vector<int> inner_iteration_ordering_used;
+ // Type of preconditioner used for solving the trust region
+ // step. Only meaningful when an iterative linear solver is used.
PreconditionerType preconditioner_type;
+ // Type of clustering algorithm used for visibility based
+ // preconditioning. Only meaningful when the preconditioner_type
+ // is CLUSTER_JACOBI or CLUSTER_TRIDIAGONAL.
+ VisibilityClusteringType visibility_clustering_type;
+
+ // Type of trust region strategy.
TrustRegionStrategyType trust_region_strategy_type;
+
+ // Type of dogleg strategy used for solving the trust region
+ // problem.
DoglegType dogleg_type;
+ // Type of the dense linear algebra library used.
DenseLinearAlgebraLibraryType dense_linear_algebra_library_type;
+
+ // Type of the sparse linear algebra library used.
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type;
+ // Type of line search direction used.
LineSearchDirectionType line_search_direction_type;
+
+ // Type of the line search algorithm used.
LineSearchType line_search_type;
+
+ // When performing line search, the degree of the polynomial used
+ // to approximate the objective function.
LineSearchInterpolationType line_search_interpolation_type;
+
+ // If the line search direction is NONLINEAR_CONJUGATE_GRADIENT,
+ // then this indicates the particular variant of non-linear
+ // conjugate gradient used.
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
+ // If the type of the line search direction is LBFGS, then this
+ // indicates the rank of the Hessian approximation.
int max_lbfgs_rank;
};
diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h
index ffa743a2d97..617bec0e1b6 100644
--- a/extern/libmv/third_party/ceres/include/ceres/types.h
+++ b/extern/libmv/third_party/ceres/include/ceres/types.h
@@ -102,21 +102,49 @@ enum PreconditionerType {
// Block diagonal of the Gauss-Newton Hessian.
JACOBI,
+ // Note: The following three preconditioners can only be used with
+ // the ITERATIVE_SCHUR solver. They are well suited for Structure
+ // from Motion problems.
+
// Block diagonal of the Schur complement. This preconditioner may
// only be used with the ITERATIVE_SCHUR solver.
SCHUR_JACOBI,
// Visibility clustering based preconditioners.
//
- // These preconditioners are well suited for Structure from Motion
- // problems, particularly problems arising from community photo
- // collections. These preconditioners use the visibility structure
- // of the scene to determine the sparsity structure of the
- // preconditioner. Requires SuiteSparse/CHOLMOD.
+ // The following two preconditioners use the visibility structure of
+ // the scene to determine the sparsity structure of the
+ // preconditioner. This is done using a clustering algorithm. The
+ // available visibility clustering algorithms are described below.
+ //
+ // Note: Requires SuiteSparse.
CLUSTER_JACOBI,
CLUSTER_TRIDIAGONAL
};
+enum VisibilityClusteringType {
+ // Canonical views algorithm as described in
+ //
+ // "Scene Summarization for Online Image Collections", Ian Simon, Noah
+ // Snavely, Steven M. Seitz, ICCV 2007.
+ //
+ // This clustering algorithm can be quite slow, but gives high
+ // quality clusters. The original visibility based clustering paper
+ // used this algorithm.
+ CANONICAL_VIEWS,
+
+ // The classic single linkage algorithm. It is extremely fast as
+ // compared to CANONICAL_VIEWS, but can give slightly poorer
+ // results. For problems with large number of cameras though, this
+ // is generally a pretty good option.
+ //
+ // If you are using SCHUR_JACOBI preconditioner and have SuiteSparse
+ // available, CLUSTER_JACOBI and CLUSTER_TRIDIAGONAL in combination
+ // with the SINGLE_LINKAGE algorithm will generally give better
+ // results.
+ SINGLE_LINKAGE
+};
+
enum SparseLinearAlgebraLibraryType {
// High performance sparse Cholesky factorization and approximate
// minimum degree ordering.
@@ -131,26 +159,6 @@ enum DenseLinearAlgebraLibraryType {
LAPACK
};
-enum LinearSolverTerminationType {
- // Termination criterion was met. For factorization based solvers
- // the tolerance is assumed to be zero. Any user provided values are
- // ignored.
- TOLERANCE,
-
- // Solver ran for max_num_iterations and terminated before the
- // termination tolerance could be satified.
- MAX_ITERATIONS,
-
- // Solver is stuck and further iterations will not result in any
- // measurable progress.
- STAGNATION,
-
- // Solver failed. Solver was terminated due to numerical errors. The
- // exact cause of failure depends on the particular solver being
- // used.
- FAILURE
-};
-
// Logging options
// The options get progressively noisier.
enum LoggingType {
@@ -400,6 +408,10 @@ bool StringToLinearSolverType(string value, LinearSolverType* type);
const char* PreconditionerTypeToString(PreconditionerType type);
bool StringToPreconditionerType(string value, PreconditionerType* type);
+const char* VisibilityClusteringTypeToString(VisibilityClusteringType type);
+bool StringToVisibilityClusteringType(string value,
+ VisibilityClusteringType* type);
+
const char* SparseLinearAlgebraLibraryTypeToString(
SparseLinearAlgebraLibraryType type);
bool StringToSparseLinearAlgebraLibraryType(
@@ -447,9 +459,6 @@ bool StringToCovarianceAlgorithmType(
string value,
CovarianceAlgorithmType* type);
-const char* LinearSolverTerminationTypeToString(
- LinearSolverTerminationType type);
-
const char* SolverTerminationTypeToString(SolverTerminationType type);
bool IsSchurType(LinearSolverType type);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
index 29974d45bc9..19b749bfc39 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc
@@ -94,7 +94,9 @@ bool BlockJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A,
//
// MatrixRef(blocks_[cells[c].block_id],
// col_block_size,
- // col_block_size).selfadjointView<Eigen::Upper>().rankUpdate(m);
+ // col_block_size)
+ // .selfadjointView<Eigen::Upper>()
+ // .rankUpdate(m);
//
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc
new file mode 100644
index 00000000000..d8bf4ef0cb5
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc
@@ -0,0 +1,120 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/block_random_access_diagonal_matrix.h"
+
+#include <algorithm>
+#include <set>
+#include <utility>
+#include <vector>
+#include "ceres/internal/port.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/triplet_sparse_matrix.h"
+#include "ceres/types.h"
+#include "ceres/stl_util.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix(
+ const vector<int>& blocks)
+ : blocks_(blocks) {
+ // Build the row/column layout vector and count the number of scalar
+ // rows/columns.
+ int num_cols = 0;
+ int num_nonzeros = 0;
+ vector<int> col_layout;
+ for (int i = 0; i < blocks_.size(); ++i) {
+ col_layout.push_back(num_cols);
+ num_cols += blocks_[i];
+ num_nonzeros += blocks_[i] * blocks_[i];
+ }
+
+ VLOG(1) << "Matrix Size [" << num_cols
+ << "," << num_cols
+ << "] " << num_nonzeros;
+
+ tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros));
+ tsm_->set_num_nonzeros(num_nonzeros);
+ int* rows = tsm_->mutable_rows();
+ int* cols = tsm_->mutable_cols();
+ double* values = tsm_->mutable_values();
+
+ int pos = 0;
+ for (int i = 0; i < blocks_.size(); ++i) {
+ const int block_size = blocks_[i];
+ layout_.push_back(new CellInfo(values + pos));
+ const int block_begin = col_layout[i];
+ for (int r = 0; r < block_size; ++r) {
+ for (int c = 0; c < block_size; ++c, ++pos) {
+ rows[pos] = block_begin + r;
+ cols[pos] = block_begin + c;
+ }
+ }
+ }
+}
+
+// Assume that the user does not hold any locks on any cell blocks
+// when they are calling SetZero.
+BlockRandomAccessDiagonalMatrix::~BlockRandomAccessDiagonalMatrix() {
+ STLDeleteContainerPointers(layout_.begin(), layout_.end());
+}
+
+CellInfo* BlockRandomAccessDiagonalMatrix::GetCell(int row_block_id,
+ int col_block_id,
+ int* row,
+ int* col,
+ int* row_stride,
+ int* col_stride) {
+ if (row_block_id != col_block_id) {
+ return NULL;
+ }
+ const int stride = blocks_[row_block_id];
+
+ // Each cell is stored contiguously as its own little dense matrix.
+ *row = 0;
+ *col = 0;
+ *row_stride = stride;
+ *col_stride = stride;
+ return layout_[row_block_id];
+}
+
+// Assume that the user does not hold any locks on any cell blocks
+// when they are calling SetZero.
+void BlockRandomAccessDiagonalMatrix::SetZero() {
+ if (tsm_->num_nonzeros()) {
+ VectorRef(tsm_->mutable_values(),
+ tsm_->num_nonzeros()).setZero();
+ }
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h
new file mode 100644
index 00000000000..6b3cff2338f
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h
@@ -0,0 +1,96 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DIAGONAL_MATRIX_H_
+#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DIAGONAL_MATRIX_H_
+
+#include <set>
+#include <vector>
+#include <utility>
+#include "ceres/mutex.h"
+#include "ceres/block_random_access_matrix.h"
+#include "ceres/collections_port.h"
+#include "ceres/triplet_sparse_matrix.h"
+#include "ceres/integral_types.h"
+#include "ceres/internal/macros.h"
+#include "ceres/internal/port.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/types.h"
+
+namespace ceres {
+namespace internal {
+
+// A thread safe block diagonal matrix implementation of
+// BlockRandomAccessMatrix.
+class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix {
+ public:
+ // blocks is an array of block sizes.
+ BlockRandomAccessDiagonalMatrix(const vector<int>& blocks);
+
+ // The destructor is not thread safe. It assumes that no one is
+ // modifying any cells when the matrix is being destroyed.
+ virtual ~BlockRandomAccessDiagonalMatrix();
+
+ // BlockRandomAccessMatrix Interface.
+ virtual CellInfo* GetCell(int row_block_id,
+ int col_block_id,
+ int* row,
+ int* col,
+ int* row_stride,
+ int* col_stride);
+
+ // This is not a thread safe method, it assumes that no cell is
+ // locked.
+ virtual void SetZero();
+
+ // Since the matrix is square, num_rows() == num_cols().
+ virtual int num_rows() const { return tsm_->num_rows(); }
+ virtual int num_cols() const { return tsm_->num_cols(); }
+
+ // Access to the underlying matrix object.
+ const TripletSparseMatrix* matrix() const { return tsm_.get(); }
+ TripletSparseMatrix* mutable_matrix() { return tsm_.get(); }
+
+ private:
+ // row/column block sizes.
+ const vector<int> blocks_;
+ vector<CellInfo*> layout_;
+
+ // The underlying matrix object which actually stores the cells.
+ scoped_ptr<TripletSparseMatrix> tsm_;
+
+ friend class BlockRandomAccessDiagonalMatrixTest;
+ CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDiagonalMatrix);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DIAGONAL_MATRIX_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
index a6b5f39a985..27b10296d6c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h
@@ -47,7 +47,7 @@
namespace ceres {
namespace internal {
-// A threaf safe square block sparse implementation of
+// A thread safe square block sparse implementation of
// BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used
// for doing the actual storage. This class augments this matrix with
// an unordered_map that allows random read/write access.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
index 653194571b1..044d4381b11 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
@@ -57,8 +57,8 @@ class CanonicalViewsClustering {
// configuration of the clustering algorithm that some of the
// vertices may not be assigned to any cluster. In this case they
// are assigned to a cluster with id = kInvalidClusterId.
- void ComputeClustering(const Graph<int>& graph,
- const CanonicalViewsClusteringOptions& options,
+ void ComputeClustering(const CanonicalViewsClusteringOptions& options,
+ const Graph<int>& graph,
vector<int>* centers,
IntMap* membership);
@@ -81,21 +81,21 @@ class CanonicalViewsClustering {
};
void ComputeCanonicalViewsClustering(
- const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
+ const Graph<int>& graph,
vector<int>* centers,
IntMap* membership) {
time_t start_time = time(NULL);
CanonicalViewsClustering cv;
- cv.ComputeClustering(graph, options, centers, membership);
+ cv.ComputeClustering(options, graph, centers, membership);
VLOG(2) << "Canonical views clustering time (secs): "
<< time(NULL) - start_time;
}
// Implementation of CanonicalViewsClustering
void CanonicalViewsClustering::ComputeClustering(
- const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
+ const Graph<int>& graph,
vector<int>* centers,
IntMap* membership) {
options_ = options;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
index 48d1ed210c9..06d80c89e92 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
@@ -47,9 +47,6 @@
#include "ceres/collections_port.h"
#include "ceres/graph.h"
-#include "ceres/internal/macros.h"
-#include "ceres/map_util.h"
-#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -100,8 +97,8 @@ struct CanonicalViewsClusteringOptions;
// algorithm that some of the vertices may not be assigned to any
// cluster. In this case they are assigned to a cluster with id = -1;
void ComputeCanonicalViewsClustering(
- const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
+ const Graph<int>& graph,
vector<int>* centers,
HashMap<int, int>* membership);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
index 9b8f9808cc9..88e61d9ed1b 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
@@ -33,6 +33,7 @@
#include "ceres/block_jacobi_preconditioner.h"
#include "ceres/cgnr_linear_operator.h"
#include "ceres/conjugate_gradients_solver.h"
+#include "ceres/internal/eigen.h"
#include "ceres/linear_solver.h"
#include "ceres/wall_time.h"
#include "glog/logging.h"
@@ -43,6 +44,10 @@ namespace internal {
CgnrSolver::CgnrSolver(const LinearSolver::Options& options)
: options_(options),
preconditioner_(NULL) {
+ if (options_.preconditioner_type != JACOBI &&
+ options_.preconditioner_type != IDENTITY) {
+ LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners.";
+ }
}
LinearSolver::Summary CgnrSolver::SolveImpl(
@@ -53,9 +58,9 @@ LinearSolver::Summary CgnrSolver::SolveImpl(
EventLogger event_logger("CgnrSolver::Solve");
// Form z = Atb.
- scoped_array<double> z(new double[A->num_cols()]);
- std::fill(z.get(), z.get() + A->num_cols(), 0.0);
- A->LeftMultiply(b, z.get());
+ Vector z(A->num_cols());
+ z.setZero();
+ A->LeftMultiply(b, z.data());
// Precondition if necessary.
LinearSolver::PerSolveOptions cg_per_solve_options = per_solve_options;
@@ -65,20 +70,17 @@ LinearSolver::Summary CgnrSolver::SolveImpl(
}
preconditioner_->Update(*A, per_solve_options.D);
cg_per_solve_options.preconditioner = preconditioner_.get();
- } else if (options_.preconditioner_type != IDENTITY) {
- LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners.";
}
// Solve (AtA + DtD)x = z (= Atb).
- std::fill(x, x + A->num_cols(), 0.0);
+ VectorRef(x, A->num_cols()).setZero();
CgnrLinearOperator lhs(*A, per_solve_options.D);
event_logger.AddEvent("Setup");
ConjugateGradientsSolver conjugate_gradient_solver(options_);
LinearSolver::Summary summary =
- conjugate_gradient_solver.Solve(&lhs, z.get(), cg_per_solve_options, x);
+ conjugate_gradient_solver.Solve(&lhs, z.data(), cg_per_solve_options, x);
event_logger.AddEvent("Solve");
-
return summary;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
index 715c975e00e..e37be528ecb 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
@@ -33,26 +33,46 @@
#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
#define CERES_INTERNAL_COLLECTIONS_PORT_H_
-#if defined(CERES_NO_TR1)
+#if defined(CERES_NO_UNORDERED_MAP)
# include <map>
# include <set>
-#else
-# if defined(_MSC_VER)
-# include <unordered_map>
-# include <unordered_set>
-# else
-# include <tr1/unordered_map>
-# include <tr1/unordered_set>
-# endif
#endif
+
+#if defined(CERES_TR1_UNORDERED_MAP)
+# include <tr1/unordered_map>
+# include <tr1/unordered_set>
+# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 {
+# define CERES_HASH_NAMESPACE_END } }
+#endif
+
+#if defined(CERES_STD_UNORDERED_MAP)
+# include <unordered_map>
+# include <unordered_set>
+# define CERES_HASH_NAMESPACE_START namespace std {
+# define CERES_HASH_NAMESPACE_END }
+#endif
+
+#if defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
+# include <unordered_map>
+# include <unordered_set>
+# define CERES_HASH_NAMESPACE_START namespace std { namespace tr1 {
+# define CERES_HASH_NAMESPACE_END } }
+#endif
+
+#if !defined(CERES_NO_UNORDERED_MAP) && !defined(CERES_TR1_UNORDERED_MAP) && \
+ !defined(CERES_STD_UNORDERED_MAP) && !defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
+# error One of: CERES_NO_UNORDERED_MAP, CERES_TR1_UNORDERED_MAP,\
+ CERES_STD_UNORDERED_MAP, CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
+#endif
+
#include <utility>
#include "ceres/integral_types.h"
#include "ceres/internal/port.h"
-// Some systems don't have access to TR1. In that case, substitute the hash
-// map/set with normal map/set. The price to pay is slightly slower speed for
-// some operations.
-#if defined(CERES_NO_TR1)
+// Some systems don't have access to unordered_map/unordered_set. In
+// that case, substitute the hash map/set with normal map/set. The
+// price to pay is slower speed for some operations.
+#if defined(CERES_NO_UNORDERED_MAP)
namespace ceres {
namespace internal {
@@ -71,11 +91,20 @@ struct HashSet : set<K> {};
namespace ceres {
namespace internal {
+#if defined(CERES_TR1_UNORDERED_MAP) || \
+ defined(CERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
template<typename K, typename V>
struct HashMap : std::tr1::unordered_map<K, V> {};
-
template<typename K>
struct HashSet : std::tr1::unordered_set<K> {};
+#endif
+
+#if defined(CERES_STD_UNORDERED_MAP)
+template<typename K, typename V>
+struct HashMap : std::unordered_map<K, V> {};
+template<typename K>
+struct HashSet : std::unordered_set<K> {};
+#endif
#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__)
#define GG_LONGLONG(x) x##I64
@@ -162,6 +191,5 @@ struct hash<pair<T, T> > {
CERES_HASH_NAMESPACE_END
-#endif // CERES_NO_TR1
-
+#endif // CERES_NO_UNORDERED_MAP
#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
index ae8e8774709..524cb8ad988 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc
@@ -44,6 +44,7 @@
#include "ceres/fpclassify.h"
#include "ceres/internal/eigen.h"
#include "ceres/linear_operator.h"
+#include "ceres/stringprintf.h"
#include "ceres/types.h"
#include "glog/logging.h"
@@ -55,9 +56,6 @@ bool IsZeroOrInfinity(double x) {
return ((x == 0.0) || (IsInfinite(x)));
}
-// Constant used in the MATLAB implementation ~ 2 * eps.
-const double kEpsilon = 2.2204e-16;
-
} // namespace
ConjugateGradientsSolver::ConjugateGradientsSolver(
@@ -76,17 +74,19 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
CHECK_EQ(A->num_rows(), A->num_cols());
LinearSolver::Summary summary;
- summary.termination_type = MAX_ITERATIONS;
+ summary.termination_type = LINEAR_SOLVER_NO_CONVERGENCE;
+ summary.message = "Maximum number of iterations reached.";
summary.num_iterations = 0;
- int num_cols = A->num_cols();
+ const int num_cols = A->num_cols();
VectorRef xref(x, num_cols);
ConstVectorRef bref(b, num_cols);
- double norm_b = bref.norm();
+ const double norm_b = bref.norm();
if (norm_b == 0.0) {
xref.setZero();
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Convergence. |b| = 0.";
return summary;
}
@@ -95,15 +95,16 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
Vector z(num_cols);
Vector tmp(num_cols);
- double tol_r = per_solve_options.r_tolerance * norm_b;
+ const double tol_r = per_solve_options.r_tolerance * norm_b;
tmp.setZero();
A->RightMultiply(x, tmp.data());
r = bref - tmp;
double norm_r = r.norm();
-
if (norm_r <= tol_r) {
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message =
+ StringPrintf("Convergence. |r| = %e <= %e.", norm_r, tol_r);
return summary;
}
@@ -115,8 +116,6 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
for (summary.num_iterations = 1;
summary.num_iterations < options_.max_num_iterations;
++summary.num_iterations) {
- VLOG(3) << "cg iteration " << summary.num_iterations;
-
// Apply preconditioner
if (per_solve_options.preconditioner != NULL) {
z.setZero();
@@ -127,10 +126,9 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
double last_rho = rho;
rho = r.dot(z);
-
if (IsZeroOrInfinity(rho)) {
- LOG(ERROR) << "Numerical failure. rho = " << rho;
- summary.termination_type = FAILURE;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = StringPrintf("Numerical failure. rho = r'z = %e.", rho);
break;
};
@@ -139,8 +137,9 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
} else {
double beta = rho / last_rho;
if (IsZeroOrInfinity(beta)) {
- LOG(ERROR) << "Numerical failure. beta = " << beta;
- summary.termination_type = FAILURE;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = StringPrintf(
+ "Numerical failure. beta = rho_n / rho_{n-1} = %e.", beta);
break;
}
p = z + beta * p;
@@ -149,18 +148,18 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
Vector& q = z;
q.setZero();
A->RightMultiply(p.data(), q.data());
- double pq = p.dot(q);
-
+ const double pq = p.dot(q);
if ((pq <= 0) || IsInfinite(pq)) {
- LOG(ERROR) << "Numerical failure. pq = " << pq;
- summary.termination_type = FAILURE;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = StringPrintf("Numerical failure. p'q = %e.", pq);
break;
}
- double alpha = rho / pq;
+ const double alpha = rho / pq;
if (IsInfinite(alpha)) {
- LOG(ERROR) << "Numerical failure. alpha " << alpha;
- summary.termination_type = FAILURE;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message =
+ StringPrintf("Numerical failure. alpha = rho / pq = %e", alpha);
break;
}
@@ -183,7 +182,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
// Quadratic model based termination.
// Q1 = x'Ax - 2 * b' x.
- double Q1 = -1.0 * xref.dot(bref + r);
+ const double Q1 = -1.0 * xref.dot(bref + r);
// For PSD matrices A, let
//
@@ -207,21 +206,23 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve(
// Journal of Computational and Applied Mathematics,
// 124(1-2), 45-59, 2000.
//
- double zeta = summary.num_iterations * (Q1 - Q0) / Q1;
- VLOG(3) << "Q termination: zeta " << zeta
- << " " << per_solve_options.q_tolerance;
+ const double zeta = summary.num_iterations * (Q1 - Q0) / Q1;
if (zeta < per_solve_options.q_tolerance) {
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message =
+ StringPrintf("Convergence: zeta = %e < %e",
+ zeta,
+ per_solve_options.q_tolerance);
break;
}
Q0 = Q1;
// Residual based termination.
norm_r = r. norm();
- VLOG(3) << "R termination: norm_r " << norm_r
- << " " << tol_r;
if (norm_r <= tol_r) {
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message =
+ StringPrintf("Convergence. |r| = %e <= %e.", norm_r, tol_r);
break;
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc
index c4da987919a..bfe93c49826 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc
@@ -227,6 +227,7 @@ void CoordinateDescentMinimizer::Solve(Program* program,
minimizer_options.evaluator = evaluator.get();
minimizer_options.jacobian = jacobian.get();
minimizer_options.trust_region_strategy = trust_region_strategy.get();
+ minimizer_options.is_silent = true;
TrustRegionMinimizer minimizer;
minimizer.Minimize(minimizer_options, parameter, summary);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
index 60269a6a4b9..581fc6d4fc0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
@@ -32,14 +32,14 @@
#include <cstddef>
#include <cmath>
+#include "ceres/internal/eigen.h"
#include "glog/logging.h"
namespace ceres {
namespace internal {
-Corrector::Corrector(double sq_norm, const double rho[3]) {
+Corrector::Corrector(const double sq_norm, const double rho[3]) {
CHECK_GE(sq_norm, 0.0);
- CHECK_GT(rho[1], 0.0);
sqrt_rho1_ = sqrt(rho[1]);
// If sq_norm = 0.0, the correction becomes trivial, the residual
@@ -84,6 +84,14 @@ Corrector::Corrector(double sq_norm, const double rho[3]) {
return;
}
+ // We now require that the first derivative of the loss function be
+ // positive only if the second derivative is positive. This is
+ // because when the second derivative is non-positive, we do not use
+ // the second order correction suggested by BANS and instead use a
+ // simpler first order strategy which does not use a division by the
+ // gradient of the loss function.
+ CHECK_GT(rho[1], 0.0);
+
// Calculate the smaller of the two solutions to the equation
//
// 0.5 * alpha^2 - alpha - rho'' / rho' * z'z = 0.
@@ -101,20 +109,25 @@ Corrector::Corrector(double sq_norm, const double rho[3]) {
alpha_sq_norm_ = alpha / sq_norm;
}
-void Corrector::CorrectResiduals(int num_rows, double* residuals) {
+void Corrector::CorrectResiduals(const int num_rows, double* residuals) {
DCHECK(residuals != NULL);
// Equation 11 in BANS.
- for (int r = 0; r < num_rows; ++r) {
- residuals[r] *= residual_scaling_;
- }
+ VectorRef(residuals, num_rows) *= residual_scaling_;
}
-void Corrector::CorrectJacobian(int num_rows,
- int num_cols,
+void Corrector::CorrectJacobian(const int num_rows,
+ const int num_cols,
double* residuals,
double* jacobian) {
DCHECK(residuals != NULL);
DCHECK(jacobian != NULL);
+
+ // The common case (rho[2] <= 0).
+ if (alpha_sq_norm_ == 0.0) {
+ VectorRef(jacobian, num_rows * num_cols) *= sqrt_rho1_;
+ return;
+ }
+
// Equation 11 in BANS.
//
// J = sqrt(rho) * (J - alpha^2 r * r' J)
diff --git a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
index 19d545cc2d3..91f0393d966 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
@@ -35,6 +35,7 @@
#endif
#include <algorithm>
+#include <cstdlib>
#include <utility>
#include <vector>
#include "Eigen/SVD"
@@ -164,9 +165,9 @@ bool CovarianceImpl::GetCovarianceBlock(const double* original_parameter_block1,
}
if (offset == row_size) {
- LOG(WARNING) << "Unable to find covariance block for "
- << original_parameter_block1 << " "
- << original_parameter_block2;
+ LOG(ERROR) << "Unable to find covariance block for "
+ << original_parameter_block1 << " "
+ << original_parameter_block2;
return false;
}
@@ -347,8 +348,8 @@ bool CovarianceImpl::ComputeCovarianceSparsity(
// values of the parameter blocks. Thus iterating over the keys of
// parameter_block_to_row_index_ corresponds to iterating over the
// rows of the covariance matrix in order.
- int i = 0; // index into covariance_blocks.
- int cursor = 0; // index into the covariance matrix.
+ int i = 0; // index into covariance_blocks.
+ int cursor = 0; // index into the covariance matrix.
for (map<const double*, int>::const_iterator it =
parameter_block_to_row_index_.begin();
it != parameter_block_to_row_index_.end();
@@ -392,12 +393,12 @@ bool CovarianceImpl::ComputeCovarianceSparsity(
bool CovarianceImpl::ComputeCovarianceValues() {
switch (options_.algorithm_type) {
- case (DENSE_SVD):
+ case DENSE_SVD:
return ComputeCovarianceValuesUsingDenseSVD();
#ifndef CERES_NO_SUITESPARSE
- case (SPARSE_CHOLESKY):
+ case SPARSE_CHOLESKY:
return ComputeCovarianceValuesUsingSparseCholesky();
- case (SPARSE_QR):
+ case SPARSE_QR:
return ComputeCovarianceValuesUsingSparseQR();
#endif
default:
@@ -440,27 +441,38 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky() {
cholmod_jacobian_view.sorted = 1;
cholmod_jacobian_view.packed = 1;
- cholmod_factor* factor = ss.AnalyzeCholesky(&cholmod_jacobian_view);
+ string status;
+ cholmod_factor* factor = ss.AnalyzeCholesky(&cholmod_jacobian_view, &status);
event_logger.AddEvent("Symbolic Factorization");
- bool factorization_succeeded = ss.Cholesky(&cholmod_jacobian_view, factor);
- if (factorization_succeeded) {
- const double reciprocal_condition_number =
- cholmod_rcond(factor, ss.mutable_cc());
- if (reciprocal_condition_number <
- options_.min_reciprocal_condition_number) {
- LOG(WARNING) << "Cholesky factorization of J'J is not reliable. "
- << "Reciprocal condition number: "
- << reciprocal_condition_number << " "
- << "min_reciprocal_condition_number : "
- << options_.min_reciprocal_condition_number;
- factorization_succeeded = false;
- }
+ if (factor == NULL) {
+ LOG(ERROR) << "Covariance estimation failed. "
+ << "CHOLMOD symbolic cholesky factorization returned with: "
+ << status;
+ return false;
}
+ LinearSolverTerminationType termination_type =
+ ss.Cholesky(&cholmod_jacobian_view, factor, &status);
event_logger.AddEvent("Numeric Factorization");
- if (!factorization_succeeded) {
+ if (termination_type != LINEAR_SOLVER_SUCCESS) {
+ LOG(ERROR) << "Covariance estimation failed. "
+ << "CHOLMOD numeric cholesky factorization returned with: "
+ << status;
+ ss.Free(factor);
+ return false;
+ }
+
+ const double reciprocal_condition_number =
+ cholmod_rcond(factor, ss.mutable_cc());
+
+ if (reciprocal_condition_number <
+ options_.min_reciprocal_condition_number) {
+ LOG(ERROR) << "Cholesky factorization of J'J is not reliable. "
+ << "Reciprocal condition number: "
+ << reciprocal_condition_number << " "
+ << "min_reciprocal_condition_number : "
+ << options_.min_reciprocal_condition_number;
ss.Free(factor);
- LOG(WARNING) << "Cholesky factorization failed.";
return false;
}
@@ -681,10 +693,10 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseQR() {
CHECK_NOTNULL(R);
if (rank < cholmod_jacobian.ncol) {
- LOG(WARNING) << "Jacobian matrix is rank deficient."
- << "Number of columns: " << cholmod_jacobian.ncol
- << " rank: " << rank;
- delete []permutation;
+ LOG(ERROR) << "Jacobian matrix is rank deficient. "
+ << "Number of columns: " << cholmod_jacobian.ncol
+ << " rank: " << rank;
+ free(permutation);
cholmod_l_free_sparse(&R, &cc);
cholmod_l_finish(&cc);
return false;
@@ -739,7 +751,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseQR() {
}
}
- delete []permutation;
+ free(permutation);
cholmod_l_free_sparse(&R, &cc);
cholmod_l_finish(&cc);
event_logger.AddEvent("Inversion");
@@ -807,11 +819,11 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() {
if (automatic_truncation) {
break;
} else {
- LOG(WARNING) << "Cholesky factorization of J'J is not reliable. "
- << "Reciprocal condition number: "
- << singular_value_ratio * singular_value_ratio << " "
- << "min_reciprocal_condition_number : "
- << options_.min_reciprocal_condition_number;
+ LOG(ERROR) << "Cholesky factorization of J'J is not reliable. "
+ << "Reciprocal condition number: "
+ << singular_value_ratio * singular_value_ratio << " "
+ << "min_reciprocal_condition_number : "
+ << options_.min_reciprocal_condition_number;
return false;
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
index c6d77439653..7145f73a2ba 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
@@ -175,8 +175,8 @@ cs_di CXSparse::CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A) {
cs_di* CXSparse::CreateSparseMatrix(TripletSparseMatrix* tsm) {
cs_di_sparse tsm_wrapper;
- tsm_wrapper.nzmax = tsm->num_nonzeros();;
- tsm_wrapper.nz = tsm->num_nonzeros();;
+ tsm_wrapper.nzmax = tsm->num_nonzeros();
+ tsm_wrapper.nz = tsm->num_nonzeros();
tsm_wrapper.m = tsm->num_rows();
tsm_wrapper.n = tsm->num_cols();
tsm_wrapper.p = tsm->mutable_cols();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
index fbf3cbec9d2..f44d6da824c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
@@ -95,9 +95,19 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingEigen(
LinearSolver::Summary summary;
summary.num_iterations = 1;
- summary.termination_type = TOLERANCE;
- VectorRef(x, num_cols) =
- lhs.selfadjointView<Eigen::Upper>().llt().solve(rhs);
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ Eigen::LLT<Matrix, Eigen::Upper> llt =
+ lhs.selfadjointView<Eigen::Upper>().llt();
+
+ if (llt.info() != Eigen::Success) {
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = "Eigen LLT decomposition failed.";
+ } else {
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+ }
+
+ VectorRef(x, num_cols) = llt.solve(rhs);
event_logger.AddEvent("Solve");
return summary;
}
@@ -142,14 +152,14 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingLAPACK(
A->matrix().transpose() * ConstVectorRef(b, A->num_rows());
event_logger.AddEvent("Product");
- const int info = LAPACK::SolveInPlaceUsingCholesky(num_cols, lhs.data(), x);
- event_logger.AddEvent("Solve");
-
LinearSolver::Summary summary;
summary.num_iterations = 1;
- summary.termination_type = info == 0 ? TOLERANCE : FAILURE;
-
- event_logger.AddEvent("TearDown");
+ summary.termination_type =
+ LAPACK::SolveInPlaceUsingCholesky(num_cols,
+ lhs.data(),
+ x,
+ &summary.message);
+ event_logger.AddEvent("Solve");
return summary;
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
index d76d58b51b5..4388357bd2d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
@@ -60,6 +60,7 @@ LinearSolver::Summary DenseQRSolver::SolveImpl(
return SolveUsingLAPACK(A, b, per_solve_options, x);
}
}
+
LinearSolver::Summary DenseQRSolver::SolveUsingLAPACK(
DenseSparseMatrix* A,
const double* b,
@@ -100,21 +101,18 @@ LinearSolver::Summary DenseQRSolver::SolveUsingLAPACK(
work_.resize(work_size);
}
- const int info = LAPACK::SolveUsingQR(lhs_.rows(),
- lhs_.cols(),
- lhs_.data(),
- work_.rows(),
- work_.data(),
- rhs_.data());
- event_logger.AddEvent("Solve");
-
LinearSolver::Summary summary;
summary.num_iterations = 1;
- if (info == 0) {
+ summary.termination_type = LAPACK::SolveInPlaceUsingQR(lhs_.rows(),
+ lhs_.cols(),
+ lhs_.data(),
+ work_.rows(),
+ work_.data(),
+ rhs_.data(),
+ &summary.message);
+ event_logger.AddEvent("Solve");
+ if (summary.termination_type == LINEAR_SOLVER_SUCCESS) {
VectorRef(x, num_cols) = rhs_.head(num_cols);
- summary.termination_type = TOLERANCE;
- } else {
- summary.termination_type = FAILURE;
}
event_logger.AddEvent("TearDown");
@@ -161,7 +159,8 @@ LinearSolver::Summary DenseQRSolver::SolveUsingEigen(
// is good enough or not.
LinearSolver::Summary summary;
summary.num_iterations = 1;
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
event_logger.AddEvent("TearDown");
return summary;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
index c85c8e5cbf5..f29376db793 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
@@ -99,7 +99,7 @@ TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
}
TrustRegionStrategy::Summary summary;
summary.num_iterations = 0;
- summary.termination_type = TOLERANCE;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
return summary;
}
@@ -135,7 +135,11 @@ TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
summary.num_iterations = linear_solver_summary.num_iterations;
summary.termination_type = linear_solver_summary.termination_type;
- if (linear_solver_summary.termination_type != FAILURE) {
+ if (linear_solver_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
+ return summary;
+ }
+
+ if (linear_solver_summary.termination_type != LINEAR_SOLVER_FAILURE) {
switch (dogleg_type_) {
// Interpolate the Cauchy point and the Gauss-Newton step.
case TRADITIONAL_DOGLEG:
@@ -146,7 +150,7 @@ TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
// Cauchy point and the (Gauss-)Newton step.
case SUBSPACE_DOGLEG:
if (!ComputeSubspaceModel(jacobian)) {
- summary.termination_type = FAILURE;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
break;
}
ComputeSubspaceDoglegStep(step);
@@ -513,7 +517,7 @@ LinearSolver::Summary DoglegStrategy::ComputeGaussNewtonStep(
const double* residuals) {
const int n = jacobian->num_cols();
LinearSolver::Summary linear_solver_summary;
- linear_solver_summary.termination_type = FAILURE;
+ linear_solver_summary.termination_type = LINEAR_SOLVER_FAILURE;
// The Jacobian matrix is often quite poorly conditioned. Thus it is
// necessary to add a diagonal matrix at the bottom to prevent the
@@ -526,7 +530,7 @@ LinearSolver::Summary DoglegStrategy::ComputeGaussNewtonStep(
// If the solve fails, the multiplier to the diagonal is increased
// up to max_mu_ by a factor of mu_increase_factor_ every time. If
// the linear solver is still not successful, the strategy returns
- // with FAILURE.
+ // with LINEAR_SOLVER_FAILURE.
//
// Next time when a new Gauss-Newton step is requested, the
// multiplier starts out from the last successful solve.
@@ -579,17 +583,21 @@ LinearSolver::Summary DoglegStrategy::ComputeGaussNewtonStep(
}
}
- if (linear_solver_summary.termination_type == FAILURE ||
+ if (linear_solver_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
+ return linear_solver_summary;
+ }
+
+ if (linear_solver_summary.termination_type == LINEAR_SOLVER_FAILURE ||
!IsArrayValid(n, gauss_newton_step_.data())) {
mu_ *= mu_increase_factor_;
VLOG(2) << "Increasing mu " << mu_;
- linear_solver_summary.termination_type = FAILURE;
+ linear_solver_summary.termination_type = LINEAR_SOLVER_FAILURE;
continue;
}
break;
}
- if (linear_solver_summary.termination_type != FAILURE) {
+ if (linear_solver_summary.termination_type != LINEAR_SOLVER_FAILURE) {
// The scaled Gauss-Newton step is D * GN:
//
// - (D^-1 J^T J D^-1)^-1 (D^-1 g)
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
index caeca69fb80..78f779f2b70 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
+++ b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
@@ -60,6 +60,7 @@ SPECIALIZATIONS = [(2, 2, 2),
(2, 4, 3),
(2, 4, 4),
(2, 4, "Eigen::Dynamic"),
+ (2, "Eigen::Dynamic", "Eigen::Dynamic"),
(4, 4, 2),
(4, 4, 3),
(4, 4, 4),
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generate_partitioned_matrix_view_specializations.py b/extern/libmv/third_party/ceres/internal/ceres/generate_partitioned_matrix_view_specializations.py
new file mode 100644
index 00000000000..c6ab573fa4b
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generate_partitioned_matrix_view_specializations.py
@@ -0,0 +1,226 @@
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2013 Google Inc. All rights reserved.
+# http://code.google.com/p/ceres-solver/
+#
+# 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: sameeragarwal@google.com (Sameer Agarwal)
+#
+# Script for explicitly generating template specialization of the
+# PartitionedMatrixView class. Explicitly generating these
+# instantiations in separate .cc files breaks the compilation into
+# separate compilation unit rather than one large cc file.
+#
+# This script creates two sets of files.
+#
+# 1. partitioned_matrix_view_x_x_x.cc
+# where the x indicates the template parameters and
+#
+# 2. partitioned_matrix_view.cc
+#
+# that contains a factory function for instantiating these classes
+# based on runtime parameters.
+#
+# The list of tuples, specializations indicates the set of
+# specializations that is generated.
+
+# Set of template specializations to generate
+SPECIALIZATIONS = [(2, 2, 2),
+ (2, 2, 3),
+ (2, 2, 4),
+ (2, 2, "Eigen::Dynamic"),
+ (2, 3, 3),
+ (2, 3, 4),
+ (2, 3, 9),
+ (2, 3, "Eigen::Dynamic"),
+ (2, 4, 3),
+ (2, 4, 4),
+ (2, 4, "Eigen::Dynamic"),
+ (2, "Eigen::Dynamic", "Eigen::Dynamic"),
+ (4, 4, 2),
+ (4, 4, 3),
+ (4, 4, 4),
+ (4, 4, "Eigen::Dynamic"),
+ ("Eigen::Dynamic", "Eigen::Dynamic", "Eigen::Dynamic")]
+HEADER = """// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+"""
+
+DYNAMIC_FILE = """
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<%s, %s, %s>;
+
+} // namespace internal
+} // namespace ceres
+"""
+
+SPECIALIZATION_FILE = """
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<%s, %s, %s>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
+"""
+
+FACTORY_FILE_HEADER = """
+#include "ceres/linear_solver.h"
+#include "ceres/partitioned_matrix_view.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+PartitionedMatrixViewBase*
+PartitionedMatrixViewBase::Create(const LinearSolver::Options& options,
+ const BlockSparseMatrix& matrix) {
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+"""
+
+FACTORY_CONDITIONAL = """ if ((options.row_block_size == %s) &&
+ (options.e_block_size == %s) &&
+ (options.f_block_size == %s)) {
+ return new PartitionedMatrixView<%s, %s, %s>(
+ matrix, options.elimination_groups[0]);
+ }
+"""
+
+FACTORY_FOOTER = """
+#endif
+ VLOG(1) << "Template specializations not found for <"
+ << options.row_block_size << ","
+ << options.e_block_size << ","
+ << options.f_block_size << ">";
+ return new PartitionedMatrixView<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+};
+
+} // namespace internal
+} // namespace ceres
+"""
+
+
+def SuffixForSize(size):
+ if size == "Eigen::Dynamic":
+ return "d"
+ return str(size)
+
+
+def SpecializationFilename(prefix, row_block_size, e_block_size, f_block_size):
+ return "_".join([prefix] + map(SuffixForSize, (row_block_size,
+ e_block_size,
+ f_block_size)))
+
+
+def Specialize():
+ """
+ Generate specialization code and the conditionals to instantiate it.
+ """
+ f = open("partitioned_matrix_view.cc", "w")
+ f.write(HEADER)
+ f.write(FACTORY_FILE_HEADER)
+
+ for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
+ output = SpecializationFilename("generated/partitioned_matrix_view",
+ row_block_size,
+ e_block_size,
+ f_block_size) + ".cc"
+ fptr = open(output, "w")
+ fptr.write(HEADER)
+
+ template = SPECIALIZATION_FILE
+ if (row_block_size == "Eigen::Dynamic" and
+ e_block_size == "Eigen::Dynamic" and
+ f_block_size == "Eigen::Dynamic"):
+ template = DYNAMIC_FILE
+
+ fptr.write(template % (row_block_size, e_block_size, f_block_size))
+ fptr.close()
+
+ f.write(FACTORY_CONDITIONAL % (row_block_size,
+ e_block_size,
+ f_block_size,
+ row_block_size,
+ e_block_size,
+ f_block_size))
+ f.write(FACTORY_FOOTER)
+ f.close()
+
+
+if __name__ == "__main__":
+ Specialize()
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
new file mode 100644
index 00000000000..3079cff83f6
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 2, 2>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
new file mode 100644
index 00000000000..d2ea113fa75
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 2, 3>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
new file mode 100644
index 00000000000..4e59910f7fc
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 2, 4>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
new file mode 100644
index 00000000000..82392958590
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 2, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
new file mode 100644
index 00000000000..b408ca5d301
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 3, 3>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
new file mode 100644
index 00000000000..fc468bf6264
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 3, 4>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
new file mode 100644
index 00000000000..3633a1c6827
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 3, 9>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
new file mode 100644
index 00000000000..83147276ab8
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 3, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
new file mode 100644
index 00000000000..04ebe93de77
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 4, 3>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
new file mode 100644
index 00000000000..5374554673d
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 4, 4>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
new file mode 100644
index 00000000000..69eccf934dd
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, 4, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
new file mode 100644
index 00000000000..32388121824
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<2, Eigen::Dynamic, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
new file mode 100644
index 00000000000..1a223ffbde8
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<4, 4, 2>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
new file mode 100644
index 00000000000..d50c18d70e1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<4, 4, 3>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
new file mode 100644
index 00000000000..adf7783c3ed
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<4, 4, 4>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
new file mode 100644
index 00000000000..06f75eaea1c
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<4, 4, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_d_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
new file mode 100644
index 00000000000..b392fd50917
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
@@ -0,0 +1,53 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+
+#include "ceres/partitioned_matrix_view_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class PartitionedMatrixView<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc
new file mode 100644
index 00000000000..4b420c371a1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc
@@ -0,0 +1,56 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of SchurEliminator.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
+
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
+#include "ceres/schur_eliminator_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class SchurEliminator<2, Eigen::Dynamic, Eigen::Dynamic>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
index 3edf95da6e0..550301359ad 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
@@ -44,7 +44,7 @@
#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
-#include "ceres/runtime_numeric_diff_cost_function.h"
+#include "ceres/dynamic_numeric_diff_cost_function.h"
#include "ceres/stringprintf.h"
#include "ceres/types.h"
#include "glog/logging.h"
@@ -84,14 +84,24 @@ class GradientCheckingCostFunction : public CostFunction {
double relative_precision,
const string& extra_info)
: function_(function),
- finite_diff_cost_function_(
- CreateRuntimeNumericDiffCostFunction(function,
- CENTRAL,
- relative_step_size)),
relative_precision_(relative_precision),
extra_info_(extra_info) {
- *mutable_parameter_block_sizes() = function->parameter_block_sizes();
+ DynamicNumericDiffCostFunction<CostFunction, CENTRAL>*
+ finite_diff_cost_function =
+ new DynamicNumericDiffCostFunction<CostFunction, CENTRAL>(
+ function,
+ DO_NOT_TAKE_OWNERSHIP,
+ relative_step_size);
+
+ const vector<int16>& parameter_block_sizes =
+ function->parameter_block_sizes();
+ for (int i = 0; i < parameter_block_sizes.size(); ++i) {
+ finite_diff_cost_function->AddParameterBlock(parameter_block_sizes[i]);
+ }
+ *mutable_parameter_block_sizes() = parameter_block_sizes;
set_num_residuals(function->num_residuals());
+ finite_diff_cost_function->SetNumResiduals(num_residuals());
+ finite_diff_cost_function_.reset(finite_diff_cost_function);
}
virtual ~GradientCheckingCostFunction() { }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
index 32722bb6e8f..2da6235f513 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc
@@ -35,21 +35,18 @@
#include "ceres/block_structure.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_solver.h"
#include "ceres/types.h"
#include "glog/logging.h"
namespace ceres {
namespace internal {
-ImplicitSchurComplement::ImplicitSchurComplement(int num_eliminate_blocks,
- bool preconditioner)
- : num_eliminate_blocks_(num_eliminate_blocks),
- preconditioner_(preconditioner),
- A_(NULL),
+ImplicitSchurComplement::ImplicitSchurComplement(
+ const LinearSolver::Options& options)
+ : options_(options),
D_(NULL),
- b_(NULL),
- block_diagonal_EtE_inverse_(NULL),
- block_diagonal_FtF_inverse_(NULL) {
+ b_(NULL) {
}
ImplicitSchurComplement::~ImplicitSchurComplement() {
@@ -61,7 +58,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A,
// Since initialization is reasonably heavy, perhaps we can save on
// constructing a new object everytime.
if (A_ == NULL) {
- A_.reset(new PartitionedMatrixView(A, num_eliminate_blocks_));
+ A_.reset(PartitionedMatrixViewBase::Create(options_, A));
}
D_ = D;
@@ -71,7 +68,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A,
// E'E and F'E.
if (block_diagonal_EtE_inverse_ == NULL) {
block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE());
- if (preconditioner_) {
+ if (options_.preconditioner_type == JACOBI) {
block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF());
}
rhs_.resize(A_->num_cols_f());
@@ -82,7 +79,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A,
tmp_f_cols_.resize(A_->num_cols_f());
} else {
A_->UpdateBlockDiagonalEtE(block_diagonal_EtE_inverse_.get());
- if (preconditioner_) {
+ if (options_.preconditioner_type == JACOBI) {
A_->UpdateBlockDiagonalFtF(block_diagonal_FtF_inverse_.get());
}
}
@@ -91,7 +88,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A,
// contributions from the diagonal D if it is non-null. Add that to
// the block diagonals and invert them.
AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get());
- if (preconditioner_) {
+ if (options_.preconditioner_type == JACOBI) {
AddDiagonalAndInvert((D_ == NULL) ? NULL : D_ + A_->num_cols_e(),
block_diagonal_FtF_inverse_.get());
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
index c1bb6e19bab..c992bdc206e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h
@@ -35,6 +35,7 @@
#define CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_
#include "ceres/linear_operator.h"
+#include "ceres/linear_solver.h"
#include "ceres/partitioned_matrix_view.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
@@ -96,7 +97,7 @@ class ImplicitSchurComplement : public LinearOperator {
//
// TODO(sameeragarwal): Get rid of the two bools below and replace
// them with enums.
- ImplicitSchurComplement(int num_eliminate_blocks, bool preconditioner);
+ ImplicitSchurComplement(const LinearSolver::Options& options);
virtual ~ImplicitSchurComplement();
// Initialize the Schur complement for a linear least squares
@@ -142,10 +143,9 @@ class ImplicitSchurComplement : public LinearOperator {
void AddDiagonalAndInvert(const double* D, BlockSparseMatrix* matrix);
void UpdateRhs();
- int num_eliminate_blocks_;
- bool preconditioner_;
+ const LinearSolver::Options& options_;
- scoped_ptr<PartitionedMatrixView> A_;
+ scoped_ptr<PartitionedMatrixViewBase> A_;
const double* D_;
const double* b_;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
index 1aac5657ce6..6de410bf80f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
@@ -38,6 +38,7 @@
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/conjugate_gradients_solver.h"
+#include "ceres/detect_structure.h"
#include "ceres/implicit_schur_complement.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
@@ -69,35 +70,36 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
EventLogger event_logger("IterativeSchurComplementSolver::Solve");
CHECK_NOTNULL(A->block_structure());
-
+ const int num_eliminate_blocks = options_.elimination_groups[0];
// Initialize a ImplicitSchurComplement object.
if (schur_complement_ == NULL) {
- schur_complement_.reset(
- new ImplicitSchurComplement(options_.elimination_groups[0],
- options_.preconditioner_type == JACOBI));
+ DetectStructure(*(A->block_structure()),
+ num_eliminate_blocks,
+ &options_.row_block_size,
+ &options_.e_block_size,
+ &options_.f_block_size);
+ schur_complement_.reset(new ImplicitSchurComplement(options_));
}
schur_complement_->Init(*A, per_solve_options.D, b);
const int num_schur_complement_blocks =
- A->block_structure()->cols.size() - options_.elimination_groups[0];
+ A->block_structure()->cols.size() - num_eliminate_blocks;
if (num_schur_complement_blocks == 0) {
VLOG(2) << "No parameter blocks left in the schur complement.";
LinearSolver::Summary cg_summary;
cg_summary.num_iterations = 0;
- cg_summary.termination_type = TOLERANCE;
+ cg_summary.termination_type = LINEAR_SOLVER_SUCCESS;
schur_complement_->BackSubstitute(NULL, x);
return cg_summary;
}
// Initialize the solution to the Schur complement system to zero.
- //
- // TODO(sameeragarwal): There maybe a better initialization than an
- // all zeros solution. Explore other cheap starting points.
reduced_linear_system_solution_.resize(schur_complement_->num_rows());
reduced_linear_system_solution_.setZero();
- // Instantiate a conjugate gradient solver that runs on the Schur complement
- // matrix with the block diagonal of the matrix F'F as the preconditioner.
+ // Instantiate a conjugate gradient solver that runs on the Schur
+ // complement matrix with the block diagonal of the matrix F'F as
+ // the preconditioner.
LinearSolver::Options cg_options;
cg_options.max_num_iterations = options_.max_num_iterations;
ConjugateGradientsSolver cg_solver(cg_options);
@@ -108,6 +110,8 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
Preconditioner::Options preconditioner_options;
preconditioner_options.type = options_.preconditioner_type;
+ preconditioner_options.visibility_clustering_type =
+ options_.visibility_clustering_type;
preconditioner_options.sparse_linear_algebra_library_type =
options_.sparse_linear_algebra_library_type;
preconditioner_options.num_threads = options_.num_threads;
@@ -149,26 +153,26 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
preconditioner_->Update(*A, per_solve_options.D);
cg_per_solve_options.preconditioner = preconditioner_.get();
}
-
event_logger.AddEvent("Setup");
LinearSolver::Summary cg_summary;
cg_summary.num_iterations = 0;
- cg_summary.termination_type = FAILURE;
+ cg_summary.termination_type = LINEAR_SOLVER_FAILURE;
+ // TODO(sameeragarwal): Refactor preconditioners to return a more
+ // sane message.
+ cg_summary.message = "Preconditioner update failed.";
if (preconditioner_update_was_successful) {
cg_summary = cg_solver.Solve(schur_complement_.get(),
schur_complement_->rhs().data(),
cg_per_solve_options,
reduced_linear_system_solution_.data());
- if (cg_summary.termination_type != FAILURE) {
+ if (cg_summary.termination_type != LINEAR_SOLVER_FAILURE &&
+ cg_summary.termination_type != LINEAR_SOLVER_FATAL_ERROR) {
schur_complement_->BackSubstitute(
reduced_linear_system_solution_.data(), x);
}
}
-
- VLOG(2) << "CG Iterations : " << cg_summary.num_iterations;
-
event_logger.AddEvent("Solve");
return cg_summary;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/lapack.cc b/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
index 73bfa69cbbd..c4f9302515e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
@@ -29,6 +29,9 @@
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/lapack.h"
+
+#include "ceres/internal/port.h"
+#include "ceres/linear_solver.h"
#include "glog/logging.h"
// C interface to the LAPACK Cholesky factorization and triangular solve.
@@ -63,12 +66,14 @@ extern "C" void dgels_(char* uplo,
namespace ceres {
namespace internal {
-int LAPACK::SolveInPlaceUsingCholesky(int num_rows,
- const double* in_lhs,
- double* rhs_and_solution) {
+LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky(
+ int num_rows,
+ const double* in_lhs,
+ double* rhs_and_solution,
+ string* status) {
#ifdef CERES_NO_LAPACK
LOG(FATAL) << "Ceres was built without a BLAS library.";
- return -1;
+ return LINEAR_SOLVER_FATAL_ERROR;
#else
char uplo = 'L';
int n = num_rows;
@@ -77,17 +82,33 @@ int LAPACK::SolveInPlaceUsingCholesky(int num_rows,
double* lhs = const_cast<double*>(in_lhs);
dpotrf_(&uplo, &n, lhs, &n, &info);
- if (info != 0) {
- LOG(INFO) << "Cholesky factorization (dpotrf) failed: " << info;
- return info;
+ if (info < 0) {
+ LOG(FATAL) << "Congratulations, you found a bug in Ceres."
+ << "Please report it."
+ << "LAPACK::dpotrf fatal error."
+ << "Argument: " << -info << " is invalid.";
+ return LINEAR_SOLVER_FATAL_ERROR;
+ }
+
+ if (info > 0) {
+ *status =
+ StringPrintf(
+ "LAPACK::dpotrf numerical failure. "
+ "The leading minor of order %d is not positive definite.", info);
+ return LINEAR_SOLVER_FAILURE;
}
dpotrs_(&uplo, &n, &nrhs, lhs, &n, rhs_and_solution, &n, &info);
- if (info != 0) {
- LOG(INFO) << "Triangular solve (dpotrs) failed: " << info;
+ if (info < 0) {
+ LOG(FATAL) << "Congratulations, you found a bug in Ceres."
+ << "Please report it."
+ << "LAPACK::dpotrs fatal error."
+ << "Argument: " << -info << " is invalid.";
+ return LINEAR_SOLVER_FATAL_ERROR;
}
- return info;
+ *status = "Success";
+ return LINEAR_SOLVER_SUCCESS;
#endif
};
@@ -113,20 +134,27 @@ int LAPACK::EstimateWorkSizeForQR(int num_rows, int num_cols) {
&lwork,
&info);
- CHECK_EQ(info, 0);
- return work;
+ if (info < 0) {
+ LOG(FATAL) << "Congratulations, you found a bug in Ceres."
+ << "Please report it."
+ << "LAPACK::dgels fatal error."
+ << "Argument: " << info << " is invalid.";
+ }
+ return static_cast<int>(work);
#endif
}
-int LAPACK::SolveUsingQR(int num_rows,
- int num_cols,
- const double* in_lhs,
- int work_size,
- double* work,
- double* rhs_and_solution) {
+LinearSolverTerminationType LAPACK::SolveInPlaceUsingQR(
+ int num_rows,
+ int num_cols,
+ const double* in_lhs,
+ int work_size,
+ double* work,
+ double* rhs_and_solution,
+ string* status) {
#ifdef CERES_NO_LAPACK
LOG(FATAL) << "Ceres was built without a LAPACK library.";
- return -1;
+ return LINEAR_SOLVER_FATAL_ERROR;
#else
char trans = 'N';
int m = num_rows;
@@ -149,7 +177,15 @@ int LAPACK::SolveUsingQR(int num_rows,
&work_size,
&info);
- return info;
+ if (info < 0) {
+ LOG(FATAL) << "Congratulations, you found a bug in Ceres."
+ << "Please report it."
+ << "LAPACK::dgels fatal error."
+ << "Argument: " << -info << " is invalid.";
+ }
+
+ *status = "Success.";
+ return LINEAR_SOLVER_SUCCESS;
#endif
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/lapack.h b/extern/libmv/third_party/ceres/internal/ceres/lapack.h
index 4f3a88c700a..53a33e1b19d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/lapack.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/lapack.h
@@ -31,6 +31,10 @@
#ifndef CERES_INTERNAL_LAPACK_H_
#define CERES_INTERNAL_LAPACK_H_
+#include <string>
+#include "ceres/internal/port.h"
+#include "ceres/linear_solver.h"
+
namespace ceres {
namespace internal {
@@ -47,10 +51,14 @@ class LAPACK {
//
// This function uses the LAPACK dpotrf and dpotrs routines.
//
- // The return value is zero if the solve is successful.
- static int SolveInPlaceUsingCholesky(int num_rows,
- const double* lhs,
- double* rhs_and_solution);
+ // The return value and the status string together describe whether
+ // the solver terminated successfully or not and if so, what was the
+ // reason for failure.
+ static LinearSolverTerminationType SolveInPlaceUsingCholesky(
+ int num_rows,
+ const double* lhs,
+ double* rhs_and_solution,
+ string* status);
// The SolveUsingQR function requires a buffer for its temporary
// computation. This function given the size of the lhs matrix will
@@ -73,13 +81,17 @@ class LAPACK {
//
// This function uses the LAPACK dgels routine.
//
- // The return value is zero if the solve is successful.
- static int SolveUsingQR(int num_rows,
- int num_cols,
- const double* lhs,
- int work_size,
- double* work,
- double* rhs_and_solution);
+ // The return value and the status string together describe whether
+ // the solver terminated successfully or not and if so, what was the
+ // reason for failure.
+ static LinearSolverTerminationType SolveInPlaceUsingQR(
+ int num_rows,
+ int num_cols,
+ const double* lhs,
+ int work_size,
+ double* work,
+ double* rhs_and_solution,
+ string* status);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc
index fad7c1f3258..ce3b69a8005 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc
@@ -105,10 +105,13 @@ TrustRegionStrategy::Summary LevenbergMarquardtStrategy::ComputeStep(
// do not need to be modified.
LinearSolver::Summary linear_solver_summary =
linear_solver_->Solve(jacobian, residuals, solve_options, step);
- if (linear_solver_summary.termination_type == FAILURE ||
- !IsArrayValid(num_parameters, step)) {
+
+ if (linear_solver_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
+ LOG(WARNING) << "Linear solver fatal error.";
+ } else if (linear_solver_summary.termination_type == LINEAR_SOLVER_FAILURE ||
+ !IsArrayValid(num_parameters, step)) {
LOG(WARNING) << "Linear solver failure. Failed to compute a finite step.";
- linear_solver_summary.termination_type = FAILURE;
+ linear_solver_summary.termination_type = LINEAR_SOLVER_FAILURE;
} else {
VectorRef(step, num_parameters) *= -1.0;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search.cc
index 8323896915a..77d1369634b 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/line_search.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search.cc
@@ -29,6 +29,9 @@
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+#include <iomanip>
+#include <iostream> // NOLINT
+
#include "ceres/line_search.h"
#include "ceres/fpclassify.h"
@@ -41,6 +44,8 @@
namespace ceres {
namespace internal {
namespace {
+// Precision used for floating point values in error message output.
+const int kErrorMessageNumericPrecision = 8;
FunctionSample ValueSample(const double x, const double value) {
FunctionSample sample;
@@ -67,10 +72,7 @@ FunctionSample ValueAndGradientSample(const double x,
// Convenience stream operator for pushing FunctionSamples into log messages.
std::ostream& operator<<(std::ostream &os,
const FunctionSample& sample) {
- os << "[x: " << sample.x << ", value: " << sample.value
- << ", gradient: " << sample.gradient << ", value_is_valid: "
- << std::boolalpha << sample.value_is_valid << ", gradient_is_valid: "
- << std::boolalpha << sample.gradient_is_valid << "]";
+ os << sample.ToDebugString();
return os;
}
@@ -170,6 +172,7 @@ double LineSearch::InterpolatingPolynomialMinimizingStepSize(
// to avoid replicating current.value_is_valid == false
// behaviour in WolfeLineSearch.
CHECK(lowerbound.value_is_valid)
+ << std::scientific << std::setprecision(kErrorMessageNumericPrecision)
<< "Ceres bug: lower-bound sample for interpolation is invalid, "
<< "please contact the developers!, interpolation_type: "
<< LineSearchInterpolationTypeToString(interpolation_type)
@@ -237,20 +240,26 @@ void ArmijoLineSearch::Search(const double step_size_estimate,
FunctionSample current = ValueAndGradientSample(step_size_estimate, 0.0, 0.0);
current.value_is_valid = false;
- const bool interpolation_uses_gradients =
+ // As the Armijo line search algorithm always uses the initial point, for
+ // which both the function value and derivative are known, when fitting a
+ // minimizing polynomial, we can fit up to a quadratic without requiring the
+ // gradient at the current query point.
+ const bool interpolation_uses_gradient_at_current_sample =
options().interpolation_type == CUBIC;
const double descent_direction_max_norm =
static_cast<const LineSearchFunction*>(function)->DirectionInfinityNorm();
++summary->num_function_evaluations;
- if (interpolation_uses_gradients) { ++summary->num_gradient_evaluations; }
+ if (interpolation_uses_gradient_at_current_sample) {
+ ++summary->num_gradient_evaluations;
+ }
current.value_is_valid =
function->Evaluate(current.x,
&current.value,
- interpolation_uses_gradients
+ interpolation_uses_gradient_at_current_sample
? &current.gradient : NULL);
current.gradient_is_valid =
- interpolation_uses_gradients && current.value_is_valid;
+ interpolation_uses_gradient_at_current_sample && current.value_is_valid;
while (!current.value_is_valid ||
current.value > (initial_cost
+ options().sufficient_decrease
@@ -291,14 +300,16 @@ void ArmijoLineSearch::Search(const double step_size_estimate,
current.x = step_size;
++summary->num_function_evaluations;
- if (interpolation_uses_gradients) { ++summary->num_gradient_evaluations; }
+ if (interpolation_uses_gradient_at_current_sample) {
+ ++summary->num_gradient_evaluations;
+ }
current.value_is_valid =
function->Evaluate(current.x,
&current.value,
- interpolation_uses_gradients
+ interpolation_uses_gradient_at_current_sample
? &current.gradient : NULL);
current.gradient_is_valid =
- interpolation_uses_gradients && current.value_is_valid;
+ interpolation_uses_gradient_at_current_sample && current.value_is_valid;
}
summary->optimal_step_size = current.x;
@@ -350,33 +361,36 @@ void WolfeLineSearch::Search(const double step_size_estimate,
&bracket_low,
&bracket_high,
&do_zoom_search,
- summary) &&
- summary->num_iterations < options().max_num_iterations) {
- // Failed to find either a valid point or a valid bracket, but we did not
- // run out of iterations.
+ summary)) {
+ // Failed to find either a valid point, a valid bracket satisfying the Wolfe
+ // conditions, or even a step size > minimum tolerance satisfying the Armijo
+ // condition.
return;
}
+
if (!do_zoom_search) {
// Either: Bracketing phase already found a point satisfying the strong
// Wolfe conditions, thus no Zoom required.
//
// Or: Bracketing failed to find a valid bracket or a point satisfying the
- // strong Wolfe conditions within max_num_iterations. As this is an
- // 'artificial' constraint, and we would otherwise fail to produce a valid
- // point when ArmijoLineSearch would succeed, we return the lowest point
- // found thus far which satsifies the Armijo condition (but not the Wolfe
- // conditions).
- CHECK(bracket_low.value_is_valid)
- << "Ceres bug: Bracketing produced an invalid bracket_low, please "
- << "contact the developers!, bracket_low: " << bracket_low
- << ", bracket_high: " << bracket_high << ", num_iterations: "
- << summary->num_iterations << ", max_num_iterations: "
- << options().max_num_iterations;
+ // strong Wolfe conditions within max_num_iterations, or whilst searching
+ // shrank the bracket width until it was below our minimum tolerance.
+ // As these are 'artificial' constraints, and we would otherwise fail to
+ // produce a valid point when ArmijoLineSearch would succeed, we return the
+ // point with the lowest cost found thus far which satsifies the Armijo
+ // condition (but not the Wolfe conditions).
summary->optimal_step_size = bracket_low.x;
summary->success = true;
return;
}
+ VLOG(3) << std::scientific << std::setprecision(kErrorMessageNumericPrecision)
+ << "Starting line search zoom phase with bracket_low: "
+ << bracket_low << ", bracket_high: " << bracket_high
+ << ", bracket width: " << fabs(bracket_low.x - bracket_high.x)
+ << ", bracket abs delta cost: "
+ << fabs(bracket_low.value - bracket_high.value);
+
// Wolfe Zoom phase: Called when the Bracketing phase finds an interval of
// non-zero, finite width that should bracket step sizes which satisfy the
// (strong) Wolfe conditions (before finding a step size that satisfies the
@@ -419,11 +433,22 @@ void WolfeLineSearch::Search(const double step_size_estimate,
summary->success = true;
}
-// Returns true iff bracket_low & bracket_high bound a bracket that contains
-// points which satisfy the strong Wolfe conditions. Otherwise, on return false,
-// if we stopped searching due to the 'artificial' condition of reaching
-// max_num_iterations, bracket_low is the step size amongst all those
-// tested, which satisfied the Armijo decrease condition and minimized f().
+// Returns true if either:
+//
+// A termination condition satisfying the (strong) Wolfe bracketing conditions
+// is found:
+//
+// - A valid point, defined as a bracket of zero width [zoom not required].
+// - A valid bracket (of width > tolerance), [zoom required].
+//
+// Or, searching was stopped due to an 'artificial' constraint, i.e. not
+// a condition imposed / required by the underlying algorithm, but instead an
+// engineering / implementation consideration. But a step which exceeds the
+// minimum step size, and satsifies the Armijo condition was still found,
+// and should thus be used [zoom not required].
+//
+// Returns false if no step size > minimum step size was found which
+// satisfies at least the Armijo condition.
bool WolfeLineSearch::BracketingPhase(
const FunctionSample& initial_position,
const double step_size_estimate,
@@ -437,23 +462,28 @@ bool WolfeLineSearch::BracketingPhase(
FunctionSample current = ValueAndGradientSample(step_size_estimate, 0.0, 0.0);
current.value_is_valid = false;
- const bool interpolation_uses_gradients =
- options().interpolation_type == CUBIC;
const double descent_direction_max_norm =
static_cast<const LineSearchFunction*>(function)->DirectionInfinityNorm();
*do_zoom_search = false;
*bracket_low = initial_position;
+ // As we require the gradient to evaluate the Wolfe condition, we always
+ // calculate it together with the value, irrespective of the interpolation
+ // type. As opposed to only calculating the gradient after the Armijo
+ // condition is satisifed, as the computational saving from this approach
+ // would be slight (perhaps even negative due to the extra call). Also,
+ // always calculating the value & gradient together protects against us
+ // reporting invalid solutions if the cost function returns slightly different
+ // function values when evaluated with / without gradients (due to numerical
+ // issues).
++summary->num_function_evaluations;
- if (interpolation_uses_gradients) { ++summary->num_gradient_evaluations; }
+ ++summary->num_gradient_evaluations;
current.value_is_valid =
function->Evaluate(current.x,
&current.value,
- interpolation_uses_gradients
- ? &current.gradient : NULL);
- current.gradient_is_valid =
- interpolation_uses_gradients && current.value_is_valid;
+ &current.gradient);
+ current.gradient_is_valid = current.value_is_valid;
while (true) {
++summary->num_iterations;
@@ -470,22 +500,14 @@ bool WolfeLineSearch::BracketingPhase(
*do_zoom_search = true;
*bracket_low = previous;
*bracket_high = current;
+ VLOG(3) << std::scientific
+ << std::setprecision(kErrorMessageNumericPrecision)
+ << "Bracket found: current step (" << current.x
+ << ") violates Armijo sufficient condition, or has passed an "
+ << "inflection point of f() based on value.";
break;
}
- // Irrespective of the interpolation type we are using, we now need the
- // gradient at the current point (which satisfies the Armijo condition)
- // in order to check the strong Wolfe conditions.
- if (!interpolation_uses_gradients) {
- ++summary->num_function_evaluations;
- ++summary->num_gradient_evaluations;
- current.value_is_valid =
- function->Evaluate(current.x,
- &current.value,
- &current.gradient);
- current.gradient_is_valid = current.value_is_valid;
- }
-
if (current.value_is_valid &&
fabs(current.gradient) <=
-options().sufficient_curvature_decrease * initial_position.gradient) {
@@ -493,6 +515,11 @@ bool WolfeLineSearch::BracketingPhase(
// valid termination point, therefore a Zoom not required.
*bracket_low = current;
*bracket_high = current;
+ VLOG(3) << std::scientific
+ << std::setprecision(kErrorMessageNumericPrecision)
+ << "Bracketing phase found step size: " << current.x
+ << ", satisfying strong Wolfe conditions, initial_position: "
+ << initial_position << ", current: " << current;
break;
} else if (current.value_is_valid && current.gradient >= 0) {
@@ -505,6 +532,29 @@ bool WolfeLineSearch::BracketingPhase(
// Note inverse ordering from first bracket case.
*bracket_low = current;
*bracket_high = previous;
+ VLOG(3) << "Bracket found: current step (" << current.x
+ << ") satisfies Armijo, but has gradient >= 0, thus have passed "
+ << "an inflection point of f().";
+ break;
+
+ } else if (current.value_is_valid &&
+ fabs(current.x - previous.x) * descent_direction_max_norm
+ < options().min_step_size) {
+ // We have shrunk the search bracket to a width less than our tolerance,
+ // and still not found either a point satisfying the strong Wolfe
+ // conditions, or a valid bracket containing such a point. Stop searching
+ // and set bracket_low to the size size amongst all those tested which
+ // minimizes f() and satisfies the Armijo condition.
+ LOG(WARNING) << "Line search failed: Wolfe bracketing phase shrank "
+ << "bracket width: " << fabs(current.x - previous.x)
+ << ", to < tolerance: " << options().min_step_size
+ << ", with descent_direction_max_norm: "
+ << descent_direction_max_norm << ", and failed to find "
+ << "a point satisfying the strong Wolfe conditions or a "
+ << "bracketing containing such a point. Accepting "
+ << "point found satisfying Armijo condition only, to "
+ << "allow continuation.";
+ *bracket_low = current;
break;
} else if (summary->num_iterations >= options().max_num_iterations) {
@@ -523,7 +573,7 @@ bool WolfeLineSearch::BracketingPhase(
*bracket_low =
current.value_is_valid && current.value < bracket_low->value
? current : *bracket_low;
- return false;
+ break;
}
// Either: f(current) is invalid; or, f(current) is valid, but does not
// satisfy the strong Wolfe conditions itself, or the conditions for
@@ -563,17 +613,22 @@ bool WolfeLineSearch::BracketingPhase(
current.x = step_size;
++summary->num_function_evaluations;
- if (interpolation_uses_gradients) { ++summary->num_gradient_evaluations; }
+ ++summary->num_gradient_evaluations;
current.value_is_valid =
function->Evaluate(current.x,
&current.value,
- interpolation_uses_gradients
- ? &current.gradient : NULL);
- current.gradient_is_valid =
- interpolation_uses_gradients && current.value_is_valid;
+ &current.gradient);
+ current.gradient_is_valid = current.value_is_valid;
+ }
+
+ // Ensure that even if a valid bracket was found, we will only mark a zoom
+ // as required if the bracket's width is greater than our minimum tolerance.
+ if (*do_zoom_search &&
+ fabs(bracket_high->x - bracket_low->x) * descent_direction_max_norm
+ < options().min_step_size) {
+ *do_zoom_search = false;
}
- // Either we have a valid point, defined as a bracket of zero width, in which
- // case no zoom is required, or a valid bracket in which to zoom.
+
return true;
}
@@ -589,6 +644,7 @@ bool WolfeLineSearch::ZoomPhase(const FunctionSample& initial_position,
Function* function = options().function;
CHECK(bracket_low.value_is_valid && bracket_low.gradient_is_valid)
+ << std::scientific << std::setprecision(kErrorMessageNumericPrecision)
<< "Ceres bug: f_low input to Wolfe Zoom invalid, please contact "
<< "the developers!, initial_position: " << initial_position
<< ", bracket_low: " << bracket_low
@@ -599,22 +655,46 @@ bool WolfeLineSearch::ZoomPhase(const FunctionSample& initial_position,
// not have been calculated (if bracket_high.value does not satisfy the
// Armijo sufficient decrease condition and interpolation method does not
// require it).
+ //
+ // We also do not require that: bracket_low.value < bracket_high.value,
+ // although this is typical. This is to deal with the case when
+ // bracket_low = initial_position, bracket_high is the first sample,
+ // and bracket_high does not satisfy the Armijo condition, but still has
+ // bracket_high.value < initial_position.value.
CHECK(bracket_high.value_is_valid)
+ << std::scientific << std::setprecision(kErrorMessageNumericPrecision)
<< "Ceres bug: f_high input to Wolfe Zoom invalid, please "
<< "contact the developers!, initial_position: " << initial_position
<< ", bracket_low: " << bracket_low
<< ", bracket_high: "<< bracket_high;
- CHECK_LT(bracket_low.gradient *
- (bracket_high.x - bracket_low.x), 0.0)
- << "Ceres bug: f_high input to Wolfe Zoom does not satisfy gradient "
- << "condition combined with f_low, please contact the developers!"
- << ", initial_position: " << initial_position
- << ", bracket_low: " << bracket_low
- << ", bracket_high: "<< bracket_high;
+
+ if (bracket_low.gradient * (bracket_high.x - bracket_low.x) >= 0) {
+ // The third condition for a valid initial bracket:
+ //
+ // 3. bracket_high is chosen after bracket_low, s.t.
+ // bracket_low.gradient * (bracket_high.x - bracket_low.x) < 0.
+ //
+ // is not satisfied. As this can happen when the users' cost function
+ // returns inconsistent gradient values relative to the function values,
+ // we do not CHECK_LT(), but we do stop processing and return an invalid
+ // value.
+ summary->error =
+ StringPrintf("Line search failed: Wolfe zoom phase passed a bracket "
+ "which does not satisfy: bracket_low.gradient * "
+ "(bracket_high.x - bracket_low.x) < 0 [%.8e !< 0] "
+ "with initial_position: %s, bracket_low: %s, bracket_high:"
+ " %s, the most likely cause of which is the cost function "
+ "returning inconsistent gradient & function values.",
+ bracket_low.gradient * (bracket_high.x - bracket_low.x),
+ initial_position.ToDebugString().c_str(),
+ bracket_low.ToDebugString().c_str(),
+ bracket_high.ToDebugString().c_str());
+ LOG(WARNING) << summary->error;
+ solution->value_is_valid = false;
+ return false;
+ }
const int num_bracketing_iterations = summary->num_iterations;
- const bool interpolation_uses_gradients =
- options().interpolation_type == CUBIC;
const double descent_direction_max_norm =
static_cast<const LineSearchFunction*>(function)->DirectionInfinityNorm();
@@ -669,15 +749,23 @@ bool WolfeLineSearch::ZoomPhase(const FunctionSample& initial_position,
upper_bound_step.x);
// No check on magnitude of step size being too small here as it is
// lower-bounded by the initial bracket start point, which was valid.
+ //
+ // As we require the gradient to evaluate the Wolfe condition, we always
+ // calculate it together with the value, irrespective of the interpolation
+ // type. As opposed to only calculating the gradient after the Armijo
+ // condition is satisifed, as the computational saving from this approach
+ // would be slight (perhaps even negative due to the extra call). Also,
+ // always calculating the value & gradient together protects against us
+ // reporting invalid solutions if the cost function returns slightly
+ // different function values when evaluated with / without gradients (due
+ // to numerical issues).
++summary->num_function_evaluations;
- if (interpolation_uses_gradients) { ++summary->num_gradient_evaluations; }
+ ++summary->num_gradient_evaluations;
solution->value_is_valid =
function->Evaluate(solution->x,
&solution->value,
- interpolation_uses_gradients
- ? &solution->gradient : NULL);
- solution->gradient_is_valid =
- interpolation_uses_gradients && solution->value_is_valid;
+ &solution->gradient);
+ solution->gradient_is_valid = solution->value_is_valid;
if (!solution->value_is_valid) {
summary->error =
StringPrintf("Line search failed: Wolfe Zoom phase found "
@@ -689,6 +777,12 @@ bool WolfeLineSearch::ZoomPhase(const FunctionSample& initial_position,
return false;
}
+ VLOG(3) << "Zoom iteration: "
+ << summary->num_iterations - num_bracketing_iterations
+ << ", bracket_low: " << bracket_low
+ << ", bracket_high: " << bracket_high
+ << ", minimizing solution: " << *solution;
+
if ((solution->value > (initial_position.value
+ options().sufficient_decrease
* initial_position.gradient
@@ -701,31 +795,13 @@ bool WolfeLineSearch::ZoomPhase(const FunctionSample& initial_position,
}
// Armijo sufficient decrease satisfied, check strong Wolfe condition.
- if (!interpolation_uses_gradients) {
- // Irrespective of the interpolation type we are using, we now need the
- // gradient at the current point (which satisfies the Armijo condition)
- // in order to check the strong Wolfe conditions.
- ++summary->num_function_evaluations;
- ++summary->num_gradient_evaluations;
- solution->value_is_valid =
- function->Evaluate(solution->x,
- &solution->value,
- &solution->gradient);
- solution->gradient_is_valid = solution->value_is_valid;
- if (!solution->value_is_valid) {
- summary->error =
- StringPrintf("Line search failed: Wolfe Zoom phase found "
- "step_size: %.5e, for which function is invalid, "
- "between low_step: %.5e and high_step: %.5e "
- "at which function is valid.",
- solution->x, bracket_low.x, bracket_high.x);
- LOG(WARNING) << summary->error;
- return false;
- }
- }
if (fabs(solution->gradient) <=
-options().sufficient_curvature_decrease * initial_position.gradient) {
// Found a valid termination point satisfying strong Wolfe conditions.
+ VLOG(3) << std::scientific
+ << std::setprecision(kErrorMessageNumericPrecision)
+ << "Zoom phase found step size: " << solution->x
+ << ", satisfying strong Wolfe conditions.";
break;
} else if (solution->gradient * (bracket_high.x - bracket_low.x) >= 0) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc
index 8ded823e5bd..a865f11f9f1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc
@@ -121,6 +121,7 @@ class LBFGS : public LineSearchDirection {
low_rank_inverse_hessian_.Update(
previous.search_direction * previous.step_size,
current.gradient - previous.gradient);
+
search_direction->setZero();
low_rank_inverse_hessian_.RightMultiply(current.gradient.data(),
search_direction->data());
@@ -176,9 +177,46 @@ class BFGS : public LineSearchDirection {
const Vector delta_gradient = current.gradient - previous.gradient;
const double delta_x_dot_delta_gradient = delta_x.dot(delta_gradient);
- if (delta_x_dot_delta_gradient <= 1e-10) {
+ // The (L)BFGS algorithm explicitly requires that the secant equation:
+ //
+ // B_{k+1} * s_k = y_k
+ //
+ // Is satisfied at each iteration, where B_{k+1} is the approximated
+ // Hessian at the k+1-th iteration, s_k = (x_{k+1} - x_{k}) and
+ // y_k = (grad_{k+1} - grad_{k}). As the approximated Hessian must be
+ // positive definite, this is equivalent to the condition:
+ //
+ // s_k^T * y_k > 0 [s_k^T * B_{k+1} * s_k = s_k^T * y_k > 0]
+ //
+ // This condition would always be satisfied if the function was strictly
+ // convex, alternatively, it is always satisfied provided that a Wolfe line
+ // search is used (even if the function is not strictly convex). See [1]
+ // (p138) for a proof.
+ //
+ // Although Ceres will always use a Wolfe line search when using (L)BFGS,
+ // practical implementation considerations mean that the line search
+ // may return a point that satisfies only the Armijo condition, and thus
+ // could violate the Secant equation. As such, we will only use a step
+ // to update the Hessian approximation if:
+ //
+ // s_k^T * y_k > tolerance
+ //
+ // It is important that tolerance is very small (and >=0), as otherwise we
+ // might skip the update too often and fail to capture important curvature
+ // information in the Hessian. For example going from 1e-10 -> 1e-14
+ // improves the NIST benchmark score from 43/54 to 53/54.
+ //
+ // [1] Nocedal J, Wright S, Numerical Optimization, 2nd Ed. Springer, 1999.
+ //
+ // TODO(alexs.mac): Consider using Damped BFGS update instead of
+ // skipping update.
+ const double kBFGSSecantConditionHessianUpdateTolerance = 1e-14;
+ if (delta_x_dot_delta_gradient <=
+ kBFGSSecantConditionHessianUpdateTolerance) {
VLOG(2) << "Skipping BFGS Update, delta_x_dot_delta_gradient too "
- << "small: " << delta_x_dot_delta_gradient;
+ << "small: " << delta_x_dot_delta_gradient << ", tolerance: "
+ << kBFGSSecantConditionHessianUpdateTolerance
+ << " (Secant condition).";
} else {
// Update dense inverse Hessian approximation.
@@ -214,8 +252,13 @@ class BFGS : public LineSearchDirection {
// Part II: Implementation and experiments, Management Science,
// 20(5), 863-874, 1974.
// [2] Nocedal J., Wright S., Numerical Optimization, Springer, 1999.
- inverse_hessian_ *=
+ const double approximate_eigenvalue_scale =
delta_x_dot_delta_gradient / delta_gradient.dot(delta_gradient);
+ inverse_hessian_ *= approximate_eigenvalue_scale;
+
+ VLOG(4) << "Applying approximate_eigenvalue_scale: "
+ << approximate_eigenvalue_scale << " to initial inverse "
+ << "Hessian approximation.";
}
initialized_ = true;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
index 2cc89faf4c4..4590afedbed 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
@@ -69,6 +69,9 @@ namespace {
// use.
const double kEpsilon = 1e-12;
+// TODO(sameeragarwal): I think there is a small bug here, in that if
+// the evaluation fails, then the state can contain garbage. Look at
+// this more carefully.
bool Evaluate(Evaluator* evaluator,
const Vector& x,
LineSearchMinimizer::State* state) {
@@ -90,6 +93,7 @@ bool Evaluate(Evaluator* evaluator,
void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
double* parameters,
Solver::Summary* summary) {
+ const bool is_not_silent = !options.is_silent;
double start_time = WallTimeInSeconds();
double iteration_start_time = start_time;
@@ -115,14 +119,16 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.step_is_successful = false;
iteration_summary.cost_change = 0.0;
iteration_summary.gradient_max_norm = 0.0;
+ iteration_summary.gradient_norm = 0.0;
iteration_summary.step_norm = 0.0;
iteration_summary.linear_solver_iterations = 0;
iteration_summary.step_solver_time_in_seconds = 0;
// Do initial cost and Jacobian evaluation.
if (!Evaluate(evaluator, x, &current_state)) {
- LOG(WARNING) << "Terminating: Cost and gradient evaluation failed.";
+ summary->error = "Terminating: Cost and gradient evaluation failed.";
summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
return;
}
@@ -130,6 +136,7 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.cost = current_state.cost + summary->fixed_cost;
iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
+ iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
// The initial gradient max_norm is bounded from below so that we do
// not divide by zero.
@@ -139,11 +146,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
options.gradient_tolerance * initial_gradient_max_norm;
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->error =
+ StringPrintf("Terminating: Gradient tolerance reached. "
+ "Relative gradient max norm: %e <= %e",
+ iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm,
+ options.gradient_tolerance);
summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating: Gradient tolerance reached."
- << "Relative gradient max norm: "
- << iteration_summary.gradient_max_norm / initial_gradient_max_norm
- << " <= " << options.gradient_tolerance;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
@@ -190,9 +200,8 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
line_search_options,
&summary->error));
if (line_search.get() == NULL) {
- LOG(ERROR) << "Ceres bug: Unable to create a LineSearch object, please "
- << "contact the developers!, error: " << summary->error;
summary->termination_type = DID_NOT_RUN;
+ LOG_IF(ERROR, is_not_silent) << summary->error;
return;
}
@@ -206,16 +215,18 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
iteration_start_time = WallTimeInSeconds();
if (iteration_summary.iteration >= options.max_num_iterations) {
+ summary->error = "Terminating: Maximum number of iterations reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG(1) << "Terminating: Maximum number of iterations reached.";
+ VLOG_IF(1, is_not_silent) << summary->error;
break;
}
const double total_solver_time = iteration_start_time - start_time +
summary->preprocessor_time_in_seconds;
if (total_solver_time >= options.max_solver_time_in_seconds) {
+ summary->error = "Terminating: Maximum solver time reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG(1) << "Terminating: Maximum solver time reached.";
+ VLOG_IF(1, is_not_silent) << summary->error;
break;
}
@@ -241,13 +252,12 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
// have already reached our specified maximum number of restarts,
// terminate optimization.
summary->error =
- StringPrintf("Line search direction failure: specified "
+ StringPrintf("Termination: Line search direction failure: specified "
"max_num_line_search_direction_restarts: %d reached.",
options.max_num_line_search_direction_restarts);
- LOG(WARNING) << summary->error << " terminating optimization.";
summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
break;
-
} else if (!line_search_status) {
// Restart line search direction with gradient descent on first iteration
// as we have not yet reached our maximum number of restarts.
@@ -255,13 +265,16 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
options.max_num_line_search_direction_restarts);
++num_line_search_direction_restarts;
- LOG(WARNING)
+ LOG_IF(WARNING, is_not_silent)
<< "Line search direction algorithm: "
- << LineSearchDirectionTypeToString(options.line_search_direction_type)
- << ", failed to produce a valid new direction at iteration: "
- << iteration_summary.iteration << ". Restarting, number of "
- << "restarts: " << num_line_search_direction_restarts << " / "
- << options.max_num_line_search_direction_restarts << " [max].";
+ << LineSearchDirectionTypeToString(
+ options.line_search_direction_type)
+ << ", failed to produce a valid new direction at "
+ << "iteration: " << iteration_summary.iteration
+ << ". Restarting, number of restarts: "
+ << num_line_search_direction_restarts << " / "
+ << options.max_num_line_search_direction_restarts
+ << " [max].";
line_search_direction.reset(
LineSearchDirection::Create(line_search_direction_options));
current_state.search_direction = -current_state.gradient;
@@ -292,8 +305,8 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
"(current_cost - previous_cost): %.5e",
initial_step_size, current_state.directional_derivative,
(current_state.cost - previous_state.cost));
- LOG(WARNING) << summary->error;
summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
break;
}
@@ -301,6 +314,18 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
current_state.cost,
current_state.directional_derivative,
&line_search_summary);
+ if (!line_search_summary.success) {
+ summary->error =
+ StringPrintf("Numerical failure in line search, failed to find "
+ "a valid step size, (did not run out of iterations) "
+ "using initial_step_size: %.5e, initial_cost: %.5e, "
+ "initial_gradient: %.5e.",
+ initial_step_size, current_state.cost,
+ current_state.directional_derivative);
+ LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = NUMERICAL_FAILURE;
+ break;
+ }
current_state.step_size = line_search_summary.optimal_step_size;
delta = current_state.step_size * current_state.search_direction;
@@ -310,20 +335,34 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
WallTimeInSeconds() - iteration_start_time;
// TODO(sameeragarwal): Collect stats.
- if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data()) ||
- !Evaluate(evaluator, x_plus_delta, &current_state)) {
- LOG(WARNING) << "Evaluation failed.";
+ //
+ // TODO(sameeragarwal): This call to Plus() directly updates the parameter
+ // vector via the VectorRef x. This is incorrect as we check the
+ // gradient and cost changes to determine if the step is accepted
+ // later, as such we could mutate x with a step that is not
+ // subsequently accepted, thus it is possible that
+ // summary->iterations.end()->x != x at termination.
+ if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) {
+ LOG_IF(WARNING, is_not_silent)
+ << "x_plus_delta = Plus(x, delta) failed. ";
+ } else if (!Evaluate(evaluator, x_plus_delta, &current_state)) {
+ LOG_IF(WARNING, is_not_silent) << "Step failed to evaluate. ";
} else {
x = x_plus_delta;
}
iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
+ iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
+
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->error =
+ StringPrintf("Terminating: Gradient tolerance reached. "
+ "Relative gradient max norm: %e <= %e. ",
+ (iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm),
+ options.gradient_tolerance);
summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating: Gradient tolerance reached."
- << "Relative gradient max norm: "
- << iteration_summary.gradient_max_norm / initial_gradient_max_norm
- << " <= " << options.gradient_tolerance;
+ VLOG_IF(1, is_not_silent) << summary->error;
break;
}
@@ -331,11 +370,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
const double absolute_function_tolerance =
options.function_tolerance * previous_state.cost;
if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
- VLOG(1) << "Terminating. Function tolerance reached. "
- << "|cost_change|/cost: "
- << fabs(iteration_summary.cost_change) / previous_state.cost
- << " <= " << options.function_tolerance;
+ summary->error =
+ StringPrintf("Terminating. Function tolerance reached. "
+ "|cost_change|/cost: %e <= %e",
+ fabs(iteration_summary.cost_change) /
+ previous_state.cost,
+ options.function_tolerance);
summary->termination_type = FUNCTION_TOLERANCE;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
index 22691b33e44..cb26356d203 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
@@ -50,6 +50,23 @@
namespace ceres {
namespace internal {
+enum LinearSolverTerminationType {
+ // Termination criterion was met.
+ LINEAR_SOLVER_SUCCESS,
+
+ // Solver ran for max_num_iterations and terminated before the
+ // termination tolerance could be satisfied.
+ LINEAR_SOLVER_NO_CONVERGENCE,
+
+ // Solver was terminated due to numerical problems, generally due to
+ // the linear system being poorly conditioned.
+ LINEAR_SOLVER_FAILURE,
+
+ // Solver failed with a fatal error that cannot be recovered from.
+ LINEAR_SOLVER_FATAL_ERROR
+};
+
+
class LinearOperator;
// Abstract base class for objects that implement algorithms for
@@ -74,6 +91,7 @@ class LinearSolver {
Options()
: type(SPARSE_NORMAL_CHOLESKY),
preconditioner_type(JACOBI),
+ visibility_clustering_type(CANONICAL_VIEWS),
dense_linear_algebra_library_type(EIGEN),
sparse_linear_algebra_library_type(SUITE_SPARSE),
use_postordering(false),
@@ -87,9 +105,8 @@ class LinearSolver {
}
LinearSolverType type;
-
PreconditionerType preconditioner_type;
-
+ VisibilityClusteringType visibility_clustering_type;
DenseLinearAlgebraLibraryType dense_linear_algebra_library_type;
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type;
@@ -243,12 +260,13 @@ class LinearSolver {
Summary()
: residual_norm(0.0),
num_iterations(-1),
- termination_type(FAILURE) {
+ termination_type(LINEAR_SOLVER_FAILURE) {
}
double residual_norm;
int num_iterations;
LinearSolverTerminationType termination_type;
+ string message;
};
virtual ~LinearSolver();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc
index 372165f9523..9aeafecfb36 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc
@@ -35,6 +35,41 @@
namespace ceres {
namespace internal {
+// The (L)BFGS algorithm explicitly requires that the secant equation:
+//
+// B_{k+1} * s_k = y_k
+//
+// Is satisfied at each iteration, where B_{k+1} is the approximated
+// Hessian at the k+1-th iteration, s_k = (x_{k+1} - x_{k}) and
+// y_k = (grad_{k+1} - grad_{k}). As the approximated Hessian must be
+// positive definite, this is equivalent to the condition:
+//
+// s_k^T * y_k > 0 [s_k^T * B_{k+1} * s_k = s_k^T * y_k > 0]
+//
+// This condition would always be satisfied if the function was strictly
+// convex, alternatively, it is always satisfied provided that a Wolfe line
+// search is used (even if the function is not strictly convex). See [1]
+// (p138) for a proof.
+//
+// Although Ceres will always use a Wolfe line search when using (L)BFGS,
+// practical implementation considerations mean that the line search
+// may return a point that satisfies only the Armijo condition, and thus
+// could violate the Secant equation. As such, we will only use a step
+// to update the Hessian approximation if:
+//
+// s_k^T * y_k > tolerance
+//
+// It is important that tolerance is very small (and >=0), as otherwise we
+// might skip the update too often and fail to capture important curvature
+// information in the Hessian. For example going from 1e-10 -> 1e-14 improves
+// the NIST benchmark score from 43/54 to 53/54.
+//
+// [1] Nocedal J., Wright S., Numerical Optimization, 2nd Ed. Springer, 1999.
+//
+// TODO(alexs.mac): Consider using Damped BFGS update instead of
+// skipping update.
+const double kLBFGSSecantConditionHessianUpdateTolerance = 1e-14;
+
LowRankInverseHessian::LowRankInverseHessian(
int num_parameters,
int max_num_corrections,
@@ -52,9 +87,12 @@ LowRankInverseHessian::LowRankInverseHessian(
bool LowRankInverseHessian::Update(const Vector& delta_x,
const Vector& delta_gradient) {
const double delta_x_dot_delta_gradient = delta_x.dot(delta_gradient);
- if (delta_x_dot_delta_gradient <= 1e-10) {
- VLOG(2) << "Skipping LBFGS Update, delta_x_dot_delta_gradient too small: "
- << delta_x_dot_delta_gradient;
+ if (delta_x_dot_delta_gradient <=
+ kLBFGSSecantConditionHessianUpdateTolerance) {
+ VLOG(2) << "Skipping L-BFGS Update, delta_x_dot_delta_gradient too "
+ << "small: " << delta_x_dot_delta_gradient << ", tolerance: "
+ << kLBFGSSecantConditionHessianUpdateTolerance
+ << " (Secant condition).";
return false;
}
@@ -133,6 +171,10 @@ void LowRankInverseHessian::RightMultiply(const double* x_ptr,
// 20(5), 863-874, 1974.
// [2] Nocedal J., Wright S., Numerical Optimization, Springer, 1999.
search_direction *= approximate_eigenvalue_scale_;
+
+ VLOG(4) << "Applying approximate_eigenvalue_scale: "
+ << approximate_eigenvalue_scale_ << " to initial inverse Hessian "
+ << "approximation.";
}
for (int i = 0; i < num_corrections_; ++i) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
index 622e9cee1d0..3d9da997d24 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
@@ -107,6 +107,7 @@ class Minimizer {
options.line_search_sufficient_curvature_decrease;
max_line_search_step_expansion =
options.max_line_search_step_expansion;
+ is_silent = false;
evaluator = NULL;
trust_region_strategy = NULL;
jacobian = NULL;
@@ -153,6 +154,8 @@ class Minimizer {
double line_search_sufficient_curvature_decrease;
double max_line_search_step_expansion;
+ // If true, then all logging is disabled.
+ bool is_silent;
// List of callbacks that are executed by the Minimizer at the end
// of each iteration.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
index 59eaff8ec1b..7936a401d0d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -27,277 +27,141 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Template specialization of PartitionedMatrixView.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+//=========================================
+//
+// This file is generated using generate_eliminator_specialization.py.
+// Editing it manually is not recommended.
-#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 10
-
+#include "ceres/linear_solver.h"
#include "ceres/partitioned_matrix_view.h"
-
-#include <algorithm>
-#include <cstring>
-#include <vector>
-#include "ceres/block_sparse_matrix.h"
-#include "ceres/block_structure.h"
#include "ceres/internal/eigen.h"
-#include "ceres/small_blas.h"
-#include "glog/logging.h"
namespace ceres {
namespace internal {
-PartitionedMatrixView::PartitionedMatrixView(
- const BlockSparseMatrix& matrix,
- int num_col_blocks_a)
- : matrix_(matrix),
- num_col_blocks_e_(num_col_blocks_a) {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
- CHECK_NOTNULL(bs);
-
- num_col_blocks_f_ = bs->cols.size() - num_col_blocks_a;
-
- // Compute the number of row blocks in E. The number of row blocks
- // in E maybe less than the number of row blocks in the input matrix
- // as some of the row blocks at the bottom may not have any
- // e_blocks. For a definition of what an e_block is, please see
- // explicit_schur_complement_solver.h
- num_row_blocks_e_ = 0;
- for (int r = 0; r < bs->rows.size(); ++r) {
- const vector<Cell>& cells = bs->rows[r].cells;
- if (cells[0].block_id < num_col_blocks_a) {
- ++num_row_blocks_e_;
- }
+PartitionedMatrixViewBase*
+PartitionedMatrixViewBase::Create(const LinearSolver::Options& options,
+ const BlockSparseMatrix& matrix) {
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 2) &&
+ (options.f_block_size == 2)) {
+ return new PartitionedMatrixView<2, 2, 2>(
+ matrix, options.elimination_groups[0]);
}
-
- // Compute the number of columns in E and F.
- num_cols_e_ = 0;
- num_cols_f_ = 0;
-
- for (int c = 0; c < bs->cols.size(); ++c) {
- const Block& block = bs->cols[c];
- if (c < num_col_blocks_a) {
- num_cols_e_ += block.size;
- } else {
- num_cols_f_ += block.size;
- }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 2) &&
+ (options.f_block_size == 3)) {
+ return new PartitionedMatrixView<2, 2, 3>(
+ matrix, options.elimination_groups[0]);
}
-
- CHECK_EQ(num_cols_e_ + num_cols_f_, matrix_.num_cols());
-}
-
-PartitionedMatrixView::~PartitionedMatrixView() {
-}
-
-// The next four methods don't seem to be particularly cache
-// friendly. This is an artifact of how the BlockStructure of the
-// input matrix is constructed. These methods will benefit from
-// multithreading as well as improved data layout.
-
-void PartitionedMatrixView::RightMultiplyE(const double* x, double* y) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
-
- // Iterate over the first num_row_blocks_e_ row blocks, and multiply
- // by the first cell in each row block.
- const double* values = matrix_.values();
- for (int r = 0; r < num_row_blocks_e_; ++r) {
- const Cell& cell = bs->rows[r].cells[0];
- const int row_block_pos = bs->rows[r].block.position;
- const int row_block_size = bs->rows[r].block.size;
- const int col_block_id = cell.block_id;
- const int col_block_pos = bs->cols[col_block_id].position;
- const int col_block_size = bs->cols[col_block_id].size;
- MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cell.position, row_block_size, col_block_size,
- x + col_block_pos,
- y + row_block_pos);
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 2) &&
+ (options.f_block_size == 4)) {
+ return new PartitionedMatrixView<2, 2, 4>(
+ matrix, options.elimination_groups[0]);
}
-}
-
-void PartitionedMatrixView::RightMultiplyF(const double* x, double* y) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
-
- // Iterate over row blocks, and if the row block is in E, then
- // multiply by all the cells except the first one which is of type
- // E. If the row block is not in E (i.e its in the bottom
- // num_row_blocks - num_row_blocks_e row blocks), then all the cells
- // are of type F and multiply by them all.
- const double* values = matrix_.values();
- for (int r = 0; r < bs->rows.size(); ++r) {
- const int row_block_pos = bs->rows[r].block.position;
- const int row_block_size = bs->rows[r].block.size;
- const vector<Cell>& cells = bs->rows[r].cells;
- for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) {
- const int col_block_id = cells[c].block_id;
- const int col_block_pos = bs->cols[col_block_id].position;
- const int col_block_size = bs->cols[col_block_id].size;
- MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cells[c].position, row_block_size, col_block_size,
- x + col_block_pos - num_cols_e(),
- y + row_block_pos);
- }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 2) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<2, 2, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
}
-}
-
-void PartitionedMatrixView::LeftMultiplyE(const double* x, double* y) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
-
- // Iterate over the first num_row_blocks_e_ row blocks, and multiply
- // by the first cell in each row block.
- const double* values = matrix_.values();
- for (int r = 0; r < num_row_blocks_e_; ++r) {
- const Cell& cell = bs->rows[r].cells[0];
- const int row_block_pos = bs->rows[r].block.position;
- const int row_block_size = bs->rows[r].block.size;
- const int col_block_id = cell.block_id;
- const int col_block_pos = bs->cols[col_block_id].position;
- const int col_block_size = bs->cols[col_block_id].size;
- MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cell.position, row_block_size, col_block_size,
- x + row_block_pos,
- y + col_block_pos);
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 3) &&
+ (options.f_block_size == 3)) {
+ return new PartitionedMatrixView<2, 3, 3>(
+ matrix, options.elimination_groups[0]);
}
-}
-
-void PartitionedMatrixView::LeftMultiplyF(const double* x, double* y) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
-
- // Iterate over row blocks, and if the row block is in E, then
- // multiply by all the cells except the first one which is of type
- // E. If the row block is not in E (i.e its in the bottom
- // num_row_blocks - num_row_blocks_e row blocks), then all the cells
- // are of type F and multiply by them all.
- const double* values = matrix_.values();
- for (int r = 0; r < bs->rows.size(); ++r) {
- const int row_block_pos = bs->rows[r].block.position;
- const int row_block_size = bs->rows[r].block.size;
- const vector<Cell>& cells = bs->rows[r].cells;
- for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) {
- const int col_block_id = cells[c].block_id;
- const int col_block_pos = bs->cols[col_block_id].position;
- const int col_block_size = bs->cols[col_block_id].size;
- MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cells[c].position, row_block_size, col_block_size,
- x + row_block_pos,
- y + col_block_pos - num_cols_e());
- }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 3) &&
+ (options.f_block_size == 4)) {
+ return new PartitionedMatrixView<2, 3, 4>(
+ matrix, options.elimination_groups[0]);
}
-}
-
-// Given a range of columns blocks of a matrix m, compute the block
-// structure of the block diagonal of the matrix m(:,
-// start_col_block:end_col_block)'m(:, start_col_block:end_col_block)
-// and return a BlockSparseMatrix with the this block structure. The
-// caller owns the result.
-BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalMatrixLayout(
- int start_col_block, int end_col_block) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
- CompressedRowBlockStructure* block_diagonal_structure =
- new CompressedRowBlockStructure;
-
- int block_position = 0;
- int diagonal_cell_position = 0;
-
- // Iterate over the column blocks, creating a new diagonal block for
- // each column block.
- for (int c = start_col_block; c < end_col_block; ++c) {
- const Block& block = bs->cols[c];
- block_diagonal_structure->cols.push_back(Block());
- Block& diagonal_block = block_diagonal_structure->cols.back();
- diagonal_block.size = block.size;
- diagonal_block.position = block_position;
-
- block_diagonal_structure->rows.push_back(CompressedRow());
- CompressedRow& row = block_diagonal_structure->rows.back();
- row.block = diagonal_block;
-
- row.cells.push_back(Cell());
- Cell& cell = row.cells.back();
- cell.block_id = c - start_col_block;
- cell.position = diagonal_cell_position;
-
- block_position += block.size;
- diagonal_cell_position += block.size * block.size;
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 3) &&
+ (options.f_block_size == 9)) {
+ return new PartitionedMatrixView<2, 3, 9>(
+ matrix, options.elimination_groups[0]);
}
-
- // Build a BlockSparseMatrix with the just computed block
- // structure.
- return new BlockSparseMatrix(block_diagonal_structure);
-}
-
-BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalEtE() const {
- BlockSparseMatrix* block_diagonal =
- CreateBlockDiagonalMatrixLayout(0, num_col_blocks_e_);
- UpdateBlockDiagonalEtE(block_diagonal);
- return block_diagonal;
-}
-
-BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalFtF() const {
- BlockSparseMatrix* block_diagonal =
- CreateBlockDiagonalMatrixLayout(
- num_col_blocks_e_, num_col_blocks_e_ + num_col_blocks_f_);
- UpdateBlockDiagonalFtF(block_diagonal);
- return block_diagonal;
-}
-
-// Similar to the code in RightMultiplyE, except instead of the matrix
-// vector multiply its an outer product.
-//
-// block_diagonal = block_diagonal(E'E)
-void PartitionedMatrixView::UpdateBlockDiagonalEtE(
- BlockSparseMatrix* block_diagonal) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
- const CompressedRowBlockStructure* block_diagonal_structure =
- block_diagonal->block_structure();
-
- block_diagonal->SetZero();
- const double* values = matrix_.values();
- for (int r = 0; r < num_row_blocks_e_ ; ++r) {
- const Cell& cell = bs->rows[r].cells[0];
- const int row_block_size = bs->rows[r].block.size;
- const int block_id = cell.block_id;
- const int col_block_size = bs->cols[block_id].size;
- const int cell_position =
- block_diagonal_structure->rows[block_id].cells[0].position;
-
- MatrixTransposeMatrixMultiply
- <Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cell.position, row_block_size, col_block_size,
- values + cell.position, row_block_size, col_block_size,
- block_diagonal->mutable_values() + cell_position,
- 0, 0, col_block_size, col_block_size);
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 3) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<2, 3, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
}
-}
-
-// Similar to the code in RightMultiplyF, except instead of the matrix
-// vector multiply its an outer product.
-//
-// block_diagonal = block_diagonal(F'F)
-//
-void PartitionedMatrixView::UpdateBlockDiagonalFtF(
- BlockSparseMatrix* block_diagonal) const {
- const CompressedRowBlockStructure* bs = matrix_.block_structure();
- const CompressedRowBlockStructure* block_diagonal_structure =
- block_diagonal->block_structure();
-
- block_diagonal->SetZero();
- const double* values = matrix_.values();
- for (int r = 0; r < bs->rows.size(); ++r) {
- const int row_block_size = bs->rows[r].block.size;
- const vector<Cell>& cells = bs->rows[r].cells;
- for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) {
- const int col_block_id = cells[c].block_id;
- const int col_block_size = bs->cols[col_block_id].size;
- const int diagonal_block_id = col_block_id - num_col_blocks_e_;
- const int cell_position =
- block_diagonal_structure->rows[diagonal_block_id].cells[0].position;
-
- MatrixTransposeMatrixMultiply
- <Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, 1>(
- values + cells[c].position, row_block_size, col_block_size,
- values + cells[c].position, row_block_size, col_block_size,
- block_diagonal->mutable_values() + cell_position,
- 0, 0, col_block_size, col_block_size);
- }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == 3)) {
+ return new PartitionedMatrixView<2, 4, 3>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == 4)) {
+ return new PartitionedMatrixView<2, 4, 4>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<2, 4, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == Eigen::Dynamic) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<2, Eigen::Dynamic, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 4) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == 2)) {
+ return new PartitionedMatrixView<4, 4, 2>(
+ matrix, options.elimination_groups[0]);
}
-}
+ if ((options.row_block_size == 4) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == 3)) {
+ return new PartitionedMatrixView<4, 4, 3>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 4) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == 4)) {
+ return new PartitionedMatrixView<4, 4, 4>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == 4) &&
+ (options.e_block_size == 4) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<4, 4, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+ }
+ if ((options.row_block_size == Eigen::Dynamic) &&
+ (options.e_block_size == Eigen::Dynamic) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new PartitionedMatrixView<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+ }
+
+#endif
+ VLOG(1) << "Template specializations not found for <"
+ << options.row_block_size << ","
+ << options.e_block_size << ","
+ << options.f_block_size << ">";
+ return new PartitionedMatrixView<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(
+ matrix, options.elimination_groups[0]);
+};
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h
index ebfbe403189..661252d404f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h
@@ -36,7 +36,15 @@
#ifndef CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_
#define CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_
-#include "ceres/block_sparse_matrix.h"
+#include <algorithm>
+#include <cstring>
+#include <vector>
+
+#include "ceres/block_structure.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/linear_solver.h"
+#include "ceres/small_blas.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -51,57 +59,80 @@ namespace internal {
// block structure of the matrix does not satisfy the requirements of
// the Schur complement solver it will result in unpredictable and
// wrong output.
-//
-// This class lives in the internal name space as its a utility class
-// to be used by the IterativeSchurComplementSolver class, found in
-// iterative_schur_complement_solver.h, and is not meant for general
-// consumption.
-class PartitionedMatrixView {
+class PartitionedMatrixViewBase {
public:
- // matrix = [E F], where the matrix E contains the first
- // num_col_blocks_a column blocks.
- PartitionedMatrixView(const BlockSparseMatrix& matrix,
- int num_col_blocks_a);
- ~PartitionedMatrixView();
+ virtual ~PartitionedMatrixViewBase() {}
// y += E'x
- void LeftMultiplyE(const double* x, double* y) const;
+ virtual void LeftMultiplyE(const double* x, double* y) const = 0;
// y += F'x
- void LeftMultiplyF(const double* x, double* y) const;
+ virtual void LeftMultiplyF(const double* x, double* y) const = 0;
// y += Ex
- void RightMultiplyE(const double* x, double* y) const;
+ virtual void RightMultiplyE(const double* x, double* y) const = 0;
// y += Fx
- void RightMultiplyF(const double* x, double* y) const;
+ virtual void RightMultiplyF(const double* x, double* y) const = 0;
// Create and return the block diagonal of the matrix E'E.
- BlockSparseMatrix* CreateBlockDiagonalEtE() const;
+ virtual BlockSparseMatrix* CreateBlockDiagonalEtE() const = 0;
- // Create and return the block diagonal of the matrix F'F.
- BlockSparseMatrix* CreateBlockDiagonalFtF() const;
+ // Create and return the block diagonal of the matrix F'F. Caller
+ // owns the result.
+ virtual BlockSparseMatrix* CreateBlockDiagonalFtF() const = 0;
// Compute the block diagonal of the matrix E'E and store it in
// block_diagonal. The matrix block_diagonal is expected to have a
// BlockStructure (preferably created using
// CreateBlockDiagonalMatrixEtE) which is has the same structure as
// the block diagonal of E'E.
- void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const;
+ virtual void UpdateBlockDiagonalEtE(
+ BlockSparseMatrix* block_diagonal) const = 0;
// Compute the block diagonal of the matrix F'F and store it in
// block_diagonal. The matrix block_diagonal is expected to have a
// BlockStructure (preferably created using
// CreateBlockDiagonalMatrixFtF) which is has the same structure as
// the block diagonal of F'F.
- void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const;
-
- int num_col_blocks_e() const { return num_col_blocks_e_; }
- int num_col_blocks_f() const { return num_col_blocks_f_; }
- int num_cols_e() const { return num_cols_e_; }
- int num_cols_f() const { return num_cols_f_; }
- int num_rows() const { return matrix_.num_rows(); }
- int num_cols() const { return matrix_.num_cols(); }
+ virtual void UpdateBlockDiagonalFtF(
+ BlockSparseMatrix* block_diagonal) const = 0;
+
+ virtual int num_col_blocks_e() const = 0;
+ virtual int num_col_blocks_f() const = 0;
+ virtual int num_cols_e() const = 0;
+ virtual int num_cols_f() const = 0;
+ virtual int num_rows() const = 0;
+ virtual int num_cols() const = 0;
+
+ static PartitionedMatrixViewBase* Create(const LinearSolver::Options& options,
+ const BlockSparseMatrix& matrix);
+};
+
+template <int kRowBlockSize = Eigen::Dynamic,
+ int kEBlockSize = Eigen::Dynamic,
+ int kFBlockSize = Eigen::Dynamic >
+class PartitionedMatrixView : public PartitionedMatrixViewBase {
+ public:
+ // matrix = [E F], where the matrix E contains the first
+ // num_col_blocks_a column blocks.
+ PartitionedMatrixView(const BlockSparseMatrix& matrix, int num_col_blocks_e);
+
+ virtual ~PartitionedMatrixView();
+ virtual void LeftMultiplyE(const double* x, double* y) const;
+ virtual void LeftMultiplyF(const double* x, double* y) const;
+ virtual void RightMultiplyE(const double* x, double* y) const;
+ virtual void RightMultiplyF(const double* x, double* y) const;
+ virtual BlockSparseMatrix* CreateBlockDiagonalEtE() const;
+ virtual BlockSparseMatrix* CreateBlockDiagonalFtF() const;
+ virtual void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const;
+ virtual void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const;
+ virtual int num_col_blocks_e() const { return num_col_blocks_e_; }
+ virtual int num_col_blocks_f() const { return num_col_blocks_f_; }
+ virtual int num_cols_e() const { return num_cols_e_; }
+ virtual int num_cols_f() const { return num_cols_f_; }
+ virtual int num_rows() const { return matrix_.num_rows(); }
+ virtual int num_cols() const { return matrix_.num_cols(); }
private:
BlockSparseMatrix* CreateBlockDiagonalMatrixLayout(int start_col_block,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view_impl.h b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view_impl.h
new file mode 100644
index 00000000000..ae7f776e6b1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view_impl.h
@@ -0,0 +1,380 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/partitioned_matrix_view.h"
+
+#include <algorithm>
+#include <cstring>
+#include <vector>
+#include "ceres/block_sparse_matrix.h"
+#include "ceres/block_structure.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/small_blas.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+PartitionedMatrixView(
+ const BlockSparseMatrix& matrix,
+ int num_col_blocks_e)
+ : matrix_(matrix),
+ num_col_blocks_e_(num_col_blocks_e) {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+ CHECK_NOTNULL(bs);
+
+ num_col_blocks_f_ = bs->cols.size() - num_col_blocks_e_;
+
+ // Compute the number of row blocks in E. The number of row blocks
+ // in E maybe less than the number of row blocks in the input matrix
+ // as some of the row blocks at the bottom may not have any
+ // e_blocks. For a definition of what an e_block is, please see
+ // explicit_schur_complement_solver.h
+ num_row_blocks_e_ = 0;
+ for (int r = 0; r < bs->rows.size(); ++r) {
+ const vector<Cell>& cells = bs->rows[r].cells;
+ if (cells[0].block_id < num_col_blocks_e_) {
+ ++num_row_blocks_e_;
+ }
+ }
+
+ // Compute the number of columns in E and F.
+ num_cols_e_ = 0;
+ num_cols_f_ = 0;
+
+ for (int c = 0; c < bs->cols.size(); ++c) {
+ const Block& block = bs->cols[c];
+ if (c < num_col_blocks_e_) {
+ num_cols_e_ += block.size;
+ } else {
+ num_cols_f_ += block.size;
+ }
+ }
+
+ CHECK_EQ(num_cols_e_ + num_cols_f_, matrix_.num_cols());
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+~PartitionedMatrixView() {
+}
+
+// The next four methods don't seem to be particularly cache
+// friendly. This is an artifact of how the BlockStructure of the
+// input matrix is constructed. These methods will benefit from
+// multithreading as well as improved data layout.
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+RightMultiplyE(const double* x, double* y) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+
+ // Iterate over the first num_row_blocks_e_ row blocks, and multiply
+ // by the first cell in each row block.
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_; ++r) {
+ const Cell& cell = bs->rows[r].cells[0];
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const int col_block_id = cell.block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixVectorMultiply<kRowBlockSize, kEBlockSize, 1>(
+ values + cell.position, row_block_size, col_block_size,
+ x + col_block_pos,
+ y + row_block_pos);
+ }
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+RightMultiplyF(const double* x, double* y) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+
+ // Iterate over row blocks, and if the row block is in E, then
+ // multiply by all the cells except the first one which is of type
+ // E. If the row block is not in E (i.e its in the bottom
+ // num_row_blocks - num_row_blocks_e row blocks), then all the cells
+ // are of type F and multiply by them all.
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_; ++r) {
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 1; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixVectorMultiply<kRowBlockSize, kFBlockSize, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ x + col_block_pos - num_cols_e_,
+ y + row_block_pos);
+ }
+ }
+
+ for (int r = num_row_blocks_e_; r < bs->rows.size(); ++r) {
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 0; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ x + col_block_pos - num_cols_e_,
+ y + row_block_pos);
+ }
+ }
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+LeftMultiplyE(const double* x, double* y) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+
+ // Iterate over the first num_row_blocks_e_ row blocks, and multiply
+ // by the first cell in each row block.
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_; ++r) {
+ const Cell& cell = bs->rows[r].cells[0];
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const int col_block_id = cell.block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixTransposeVectorMultiply<kRowBlockSize, kEBlockSize, 1>(
+ values + cell.position, row_block_size, col_block_size,
+ x + row_block_pos,
+ y + col_block_pos);
+ }
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+LeftMultiplyF(const double* x, double* y) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+
+ // Iterate over row blocks, and if the row block is in E, then
+ // multiply by all the cells except the first one which is of type
+ // E. If the row block is not in E (i.e its in the bottom
+ // num_row_blocks - num_row_blocks_e row blocks), then all the cells
+ // are of type F and multiply by them all.
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_; ++r) {
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 1; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixTransposeVectorMultiply<kRowBlockSize, kFBlockSize, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ x + row_block_pos,
+ y + col_block_pos - num_cols_e_);
+ }
+ }
+
+ for (int r = num_row_blocks_e_; r < bs->rows.size(); ++r) {
+ const int row_block_pos = bs->rows[r].block.position;
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 0; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_pos = bs->cols[col_block_id].position;
+ const int col_block_size = bs->cols[col_block_id].size;
+ MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ x + row_block_pos,
+ y + col_block_pos - num_cols_e_);
+ }
+ }
+}
+
+// Given a range of columns blocks of a matrix m, compute the block
+// structure of the block diagonal of the matrix m(:,
+// start_col_block:end_col_block)'m(:, start_col_block:end_col_block)
+// and return a BlockSparseMatrix with the this block structure. The
+// caller owns the result.
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+BlockSparseMatrix*
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+CreateBlockDiagonalMatrixLayout(int start_col_block, int end_col_block) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+ CompressedRowBlockStructure* block_diagonal_structure =
+ new CompressedRowBlockStructure;
+
+ int block_position = 0;
+ int diagonal_cell_position = 0;
+
+ // Iterate over the column blocks, creating a new diagonal block for
+ // each column block.
+ for (int c = start_col_block; c < end_col_block; ++c) {
+ const Block& block = bs->cols[c];
+ block_diagonal_structure->cols.push_back(Block());
+ Block& diagonal_block = block_diagonal_structure->cols.back();
+ diagonal_block.size = block.size;
+ diagonal_block.position = block_position;
+
+ block_diagonal_structure->rows.push_back(CompressedRow());
+ CompressedRow& row = block_diagonal_structure->rows.back();
+ row.block = diagonal_block;
+
+ row.cells.push_back(Cell());
+ Cell& cell = row.cells.back();
+ cell.block_id = c - start_col_block;
+ cell.position = diagonal_cell_position;
+
+ block_position += block.size;
+ diagonal_cell_position += block.size * block.size;
+ }
+
+ // Build a BlockSparseMatrix with the just computed block
+ // structure.
+ return new BlockSparseMatrix(block_diagonal_structure);
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+BlockSparseMatrix*
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+CreateBlockDiagonalEtE() const {
+ BlockSparseMatrix* block_diagonal =
+ CreateBlockDiagonalMatrixLayout(0, num_col_blocks_e_);
+ UpdateBlockDiagonalEtE(block_diagonal);
+ return block_diagonal;
+}
+
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+BlockSparseMatrix*
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+CreateBlockDiagonalFtF() const {
+ BlockSparseMatrix* block_diagonal =
+ CreateBlockDiagonalMatrixLayout(
+ num_col_blocks_e_, num_col_blocks_e_ + num_col_blocks_f_);
+ UpdateBlockDiagonalFtF(block_diagonal);
+ return block_diagonal;
+}
+
+// Similar to the code in RightMultiplyE, except instead of the matrix
+// vector multiply its an outer product.
+//
+// block_diagonal = block_diagonal(E'E)
+//
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+UpdateBlockDiagonalEtE(
+ BlockSparseMatrix* block_diagonal) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+ const CompressedRowBlockStructure* block_diagonal_structure =
+ block_diagonal->block_structure();
+
+ block_diagonal->SetZero();
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_ ; ++r) {
+ const Cell& cell = bs->rows[r].cells[0];
+ const int row_block_size = bs->rows[r].block.size;
+ const int block_id = cell.block_id;
+ const int col_block_size = bs->cols[block_id].size;
+ const int cell_position =
+ block_diagonal_structure->rows[block_id].cells[0].position;
+
+ MatrixTransposeMatrixMultiply
+ <kRowBlockSize, kEBlockSize, kRowBlockSize, kEBlockSize, 1>(
+ values + cell.position, row_block_size, col_block_size,
+ values + cell.position, row_block_size, col_block_size,
+ block_diagonal->mutable_values() + cell_position,
+ 0, 0, col_block_size, col_block_size);
+ }
+}
+
+// Similar to the code in RightMultiplyF, except instead of the matrix
+// vector multiply its an outer product.
+//
+// block_diagonal = block_diagonal(F'F)
+//
+template <int kRowBlockSize, int kEBlockSize, int kFBlockSize>
+void
+PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>::
+UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const {
+ const CompressedRowBlockStructure* bs = matrix_.block_structure();
+ const CompressedRowBlockStructure* block_diagonal_structure =
+ block_diagonal->block_structure();
+
+ block_diagonal->SetZero();
+ const double* values = matrix_.values();
+ for (int r = 0; r < num_row_blocks_e_; ++r) {
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 1; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_size = bs->cols[col_block_id].size;
+ const int diagonal_block_id = col_block_id - num_col_blocks_e_;
+ const int cell_position =
+ block_diagonal_structure->rows[diagonal_block_id].cells[0].position;
+
+ MatrixTransposeMatrixMultiply
+ <kRowBlockSize, kFBlockSize, kRowBlockSize, kFBlockSize, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ values + cells[c].position, row_block_size, col_block_size,
+ block_diagonal->mutable_values() + cell_position,
+ 0, 0, col_block_size, col_block_size);
+ }
+ }
+
+ for (int r = num_row_blocks_e_; r < bs->rows.size(); ++r) {
+ const int row_block_size = bs->rows[r].block.size;
+ const vector<Cell>& cells = bs->rows[r].cells;
+ for (int c = 0; c < cells.size(); ++c) {
+ const int col_block_id = cells[c].block_id;
+ const int col_block_size = bs->cols[col_block_id].size;
+ const int diagonal_block_id = col_block_id - num_col_blocks_e_;
+ const int cell_position =
+ block_diagonal_structure->rows[diagonal_block_id].cells[0].position;
+
+ MatrixTransposeMatrixMultiply
+ <Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, 1>(
+ values + cells[c].position, row_block_size, col_block_size,
+ values + cells[c].position, row_block_size, col_block_size,
+ block_diagonal->mutable_values() + cell_position,
+ 0, 0, col_block_size, col_block_size);
+ }
+ }
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc b/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc
index 3238b89670e..c4b0243d4f6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc
@@ -37,6 +37,7 @@
#include "Eigen/Dense"
#include "ceres/internal/port.h"
+#include "ceres/stringprintf.h"
#include "glog/logging.h"
namespace ceres {
@@ -121,6 +122,63 @@ Vector RemoveLeadingZeros(const Vector& polynomial_in) {
}
} // namespace
+void FindLinearPolynomialRoots(const Vector& polynomial,
+ Vector* real,
+ Vector* imaginary) {
+ CHECK_EQ(polynomial.size(), 2);
+ if (real != NULL) {
+ real->resize(1);
+ (*real)(0) = -polynomial(1) / polynomial(0);
+ }
+
+ if (imaginary != NULL) {
+ imaginary->setZero(1);
+ }
+}
+
+void FindQuadraticPolynomialRoots(const Vector& polynomial,
+ Vector* real,
+ Vector* imaginary) {
+ CHECK_EQ(polynomial.size(), 3);
+ const double a = polynomial(0);
+ const double b = polynomial(1);
+ const double c = polynomial(2);
+ const double D = b * b - 4 * a * c;
+ const double sqrt_D = sqrt(fabs(D));
+ if (real != NULL) {
+ real->setZero(2);
+ }
+ if (imaginary != NULL) {
+ imaginary->setZero(2);
+ }
+
+ // Real roots.
+ if (D >= 0) {
+ if (real != NULL) {
+ // Stable quadratic roots according to BKP Horn.
+ // http://people.csail.mit.edu/bkph/articles/Quadratics.pdf
+ if (b >= 0) {
+ (*real)(0) = (-b - sqrt_D) / (2.0 * a);
+ (*real)(1) = (2.0 * c) / (-b - sqrt_D);
+ } else {
+ (*real)(0) = (2.0 * c) / (-b + sqrt_D);
+ (*real)(1) = (-b + sqrt_D) / (2.0 * a);
+ }
+ }
+ return;
+ }
+
+ // Use the normal quadratic formula for the complex case.
+ if (real != NULL) {
+ (*real)(0) = -b / (2.0 * a);
+ (*real)(1) = -b / (2.0 * a);
+ }
+ if (imaginary != NULL) {
+ (*imaginary)(0) = sqrt_D / (2.0 * a);
+ (*imaginary)(1) = -sqrt_D / (2.0 * a);
+ }
+}
+
bool FindPolynomialRoots(const Vector& polynomial_in,
Vector* real,
Vector* imaginary) {
@@ -132,30 +190,40 @@ bool FindPolynomialRoots(const Vector& polynomial_in,
Vector polynomial = RemoveLeadingZeros(polynomial_in);
const int degree = polynomial.size() - 1;
+ VLOG(3) << "Input polynomial: " << polynomial_in.transpose();
+ if (polynomial.size() != polynomial_in.size()) {
+ VLOG(3) << "Trimmed polynomial: " << polynomial.transpose();
+ }
+
// Is the polynomial constant?
if (degree == 0) {
LOG(WARNING) << "Trying to extract roots from a constant "
<< "polynomial in FindPolynomialRoots";
+ // We return true with no roots, not false, as if the polynomial is constant
+ // it is correct that there are no roots. It is not the case that they were
+ // there, but that we have failed to extract them.
+ return true;
+ }
+
+ // Linear
+ if (degree == 1) {
+ FindLinearPolynomialRoots(polynomial, real, imaginary);
+ return true;
+ }
+
+ // Quadratic
+ if (degree == 2) {
+ FindQuadraticPolynomialRoots(polynomial, real, imaginary);
return true;
}
+ // The degree is now known to be at least 3. For cubic or higher
+ // roots we use the method of companion matrices.
+
// Divide by leading term
const double leading_term = polynomial(0);
polynomial /= leading_term;
- // Separately handle linear polynomials.
- if (degree == 1) {
- if (real != NULL) {
- real->resize(1);
- (*real)(0) = -polynomial(1);
- }
- if (imaginary != NULL) {
- imaginary->resize(1);
- imaginary->setZero();
- }
- }
-
- // The degree is now known to be at least 2.
// Build and balance the companion matrix to the polynomial.
Matrix companion_matrix(degree, degree);
BuildCompanionMatrix(polynomial, &companion_matrix);
@@ -255,6 +323,12 @@ void MinimizePolynomial(const Vector& polynomial,
}
}
+string FunctionSample::ToDebugString() const {
+ return StringPrintf("[x: %.8e, value: %.8e, gradient: %.8e, "
+ "value_is_valid: %d, gradient_is_valid: %d]",
+ x, value, gradient, value_is_valid, gradient_is_valid);
+}
+
Vector FindInterpolatingPolynomial(const vector<FunctionSample>& samples) {
const int num_samples = samples.size();
int num_constraints = 0;
@@ -268,6 +342,7 @@ Vector FindInterpolatingPolynomial(const vector<FunctionSample>& samples) {
}
const int degree = num_constraints - 1;
+
Matrix lhs = Matrix::Zero(num_constraints, num_constraints);
Vector rhs = Vector::Zero(num_constraints);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial.h b/extern/libmv/third_party/ceres/internal/ceres/polynomial.h
index 42ffdcb13c5..80ce77e6ae1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/polynomial.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial.h
@@ -95,6 +95,7 @@ struct FunctionSample {
gradient(0.0),
gradient_is_valid(false) {
}
+ string ToDebugString() const;
double x;
double value; // value = f(x)
diff --git a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h
index af64e3c9a44..21cbc00b542 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h
@@ -48,6 +48,7 @@ class Preconditioner : public LinearOperator {
struct Options {
Options()
: type(JACOBI),
+ visibility_clustering_type(CANONICAL_VIEWS),
sparse_linear_algebra_library_type(SUITE_SPARSE),
num_threads(1),
row_block_size(Eigen::Dynamic),
@@ -56,7 +57,7 @@ class Preconditioner : public LinearOperator {
}
PreconditionerType type;
-
+ VisibilityClusteringType visibility_clustering_type;
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type;
// If possible, how many threads the preconditioner can use.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem.cc b/extern/libmv/third_party/ceres/internal/ceres/problem.cc
index 403e96a3ade..89821b9e360 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -218,4 +218,23 @@ void Problem::GetParameterBlocks(vector<double*>* parameter_blocks) const {
problem_impl_->GetParameterBlocks(parameter_blocks);
}
+void Problem::GetResidualBlocks(
+ vector<ResidualBlockId>* residual_blocks) const {
+ problem_impl_->GetResidualBlocks(residual_blocks);
+}
+
+void Problem::GetParameterBlocksForResidualBlock(
+ const ResidualBlockId residual_block,
+ vector<double*>* parameter_blocks) const {
+ problem_impl_->GetParameterBlocksForResidualBlock(residual_block,
+ parameter_blocks);
+}
+
+void Problem::GetResidualBlocksForParameterBlock(
+ const double* values,
+ vector<ResidualBlockId>* residual_blocks) const {
+ problem_impl_->GetResidualBlocksForParameterBlock(values,
+ residual_blocks);
+}
+
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
index 830270269c3..ae87fcb0317 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-// keir@google.com (Keir Mierle)
+// mierle@gmail.com (Keir Mierle)
#include "ceres/problem_impl.h"
@@ -452,7 +452,11 @@ template<typename Block>
void ProblemImpl::DeleteBlockInVector(vector<Block*>* mutable_blocks,
Block* block_to_remove) {
CHECK_EQ((*mutable_blocks)[block_to_remove->index()], block_to_remove)
- << "You found a Ceres bug! Block: " << block_to_remove->ToString();
+ << "You found a Ceres bug! \n"
+ << "Block requested: "
+ << block_to_remove->ToString() << "\n"
+ << "Block present: "
+ << (*mutable_blocks)[block_to_remove->index()]->ToString();
// Prepare the to-be-moved block for the new, lower-in-index position by
// setting the index to the blocks final location.
@@ -731,6 +735,57 @@ void ProblemImpl::GetParameterBlocks(vector<double*>* parameter_blocks) const {
}
}
+void ProblemImpl::GetResidualBlocks(
+ vector<ResidualBlockId>* residual_blocks) const {
+ CHECK_NOTNULL(residual_blocks);
+ *residual_blocks = program().residual_blocks();
+}
+
+void ProblemImpl::GetParameterBlocksForResidualBlock(
+ const ResidualBlockId residual_block,
+ vector<double*>* parameter_blocks) const {
+ int num_parameter_blocks = residual_block->NumParameterBlocks();
+ CHECK_NOTNULL(parameter_blocks)->resize(num_parameter_blocks);
+ for (int i = 0; i < num_parameter_blocks; ++i) {
+ (*parameter_blocks)[i] =
+ residual_block->parameter_blocks()[i]->mutable_user_state();
+ }
+}
+
+void ProblemImpl::GetResidualBlocksForParameterBlock(
+ const double* values,
+ vector<ResidualBlockId>* residual_blocks) const {
+ ParameterBlock* parameter_block =
+ FindParameterBlockOrDie(parameter_block_map_,
+ const_cast<double*>(values));
+
+ if (options_.enable_fast_parameter_block_removal) {
+ // In this case the residual blocks that depend on the parameter block are
+ // stored in the parameter block already, so just copy them out.
+ CHECK_NOTNULL(residual_blocks)->resize(
+ parameter_block->mutable_residual_blocks()->size());
+ std::copy(parameter_block->mutable_residual_blocks()->begin(),
+ parameter_block->mutable_residual_blocks()->end(),
+ residual_blocks->begin());
+ return;
+ }
+
+ // Find residual blocks that depend on the parameter block.
+ CHECK_NOTNULL(residual_blocks)->clear();
+ const int num_residual_blocks = NumResidualBlocks();
+ for (int i = 0; i < num_residual_blocks; ++i) {
+ ResidualBlock* residual_block =
+ (*(program_->mutable_residual_blocks()))[i];
+ const int num_parameter_blocks = residual_block->NumParameterBlocks();
+ for (int j = 0; j < num_parameter_blocks; ++j) {
+ if (residual_block->parameter_blocks()[j] == parameter_block) {
+ residual_blocks->push_back(residual_block);
+ // The parameter blocks are guaranteed unique.
+ break;
+ }
+ }
+ }
+}
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
index ace27f56bb1..35c16cd8392 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
@@ -142,6 +142,15 @@ class ProblemImpl {
int ParameterBlockSize(const double* parameter_block) const;
int ParameterBlockLocalSize(const double* parameter_block) const;
void GetParameterBlocks(vector<double*>* parameter_blocks) const;
+ void GetResidualBlocks(vector<ResidualBlockId>* residual_blocks) const;
+
+ void GetParameterBlocksForResidualBlock(
+ const ResidualBlockId residual_block,
+ vector<double*>* parameter_blocks) const;
+
+ void GetResidualBlocksForParameterBlock(
+ const double* values,
+ vector<ResidualBlockId>* residual_blocks) const;
const Program& program() const { return *program_; }
Program* mutable_program() { return program_.get(); }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc
deleted file mode 100644
index 7af275c1dd8..00000000000
--- a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
-// http://code.google.com/p/ceres-solver/
-//
-// 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: keir@google.com (Keir Mierle)
-//
-// Based on the templated version in public/numeric_diff_cost_function.h.
-
-#include "ceres/runtime_numeric_diff_cost_function.h"
-
-#include <algorithm>
-#include <numeric>
-#include <vector>
-#include "Eigen/Dense"
-#include "ceres/cost_function.h"
-#include "ceres/internal/scoped_ptr.h"
-#include "glog/logging.h"
-
-namespace ceres {
-namespace internal {
-namespace {
-
-bool EvaluateJacobianForParameterBlock(const CostFunction* function,
- int parameter_block_size,
- int parameter_block,
- RuntimeNumericDiffMethod method,
- double relative_step_size,
- double const* residuals_at_eval_point,
- double** parameters,
- double** jacobians) {
- using Eigen::Map;
- using Eigen::Matrix;
- using Eigen::Dynamic;
- using Eigen::RowMajor;
-
- typedef Matrix<double, Dynamic, 1> ResidualVector;
- typedef Matrix<double, Dynamic, 1> ParameterVector;
- typedef Matrix<double, Dynamic, Dynamic, RowMajor> JacobianMatrix;
-
- int num_residuals = function->num_residuals();
-
- Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block],
- num_residuals,
- parameter_block_size);
-
- // Mutate one element at a time and then restore.
- Map<ParameterVector> x_plus_delta(parameters[parameter_block],
- parameter_block_size);
- ParameterVector x(x_plus_delta);
- ParameterVector step_size = x.array().abs() * relative_step_size;
-
- // To handle cases where a paremeter is exactly zero, instead use the mean
- // step_size for the other dimensions.
- double fallback_step_size = step_size.sum() / step_size.rows();
- if (fallback_step_size == 0.0) {
- // If all the parameters are zero, there's no good answer. Use the given
- // relative step_size as absolute step_size and hope for the best.
- fallback_step_size = relative_step_size;
- }
-
- // For each parameter in the parameter block, use finite differences to
- // compute the derivative for that parameter.
- for (int j = 0; j < parameter_block_size; ++j) {
- if (step_size(j) == 0.0) {
- // The parameter is exactly zero, so compromise and use the mean step_size
- // from the other parameters. This can break in many cases, but it's hard
- // to pick a good number without problem specific knowledge.
- step_size(j) = fallback_step_size;
- }
- x_plus_delta(j) = x(j) + step_size(j);
-
- ResidualVector residuals(num_residuals);
- if (!function->Evaluate(parameters, &residuals[0], NULL)) {
- // Something went wrong; bail.
- return false;
- }
-
- // Compute this column of the jacobian in 3 steps:
- // 1. Store residuals for the forward part.
- // 2. Subtract residuals for the backward (or 0) part.
- // 3. Divide out the run.
- parameter_jacobian.col(j) = residuals;
-
- double one_over_h = 1 / step_size(j);
- if (method == CENTRAL) {
- // Compute the function on the other side of x(j).
- x_plus_delta(j) = x(j) - step_size(j);
-
- if (!function->Evaluate(parameters, &residuals[0], NULL)) {
- // Something went wrong; bail.
- return false;
- }
- parameter_jacobian.col(j) -= residuals;
- one_over_h /= 2;
- } else {
- // Forward difference only; reuse existing residuals evaluation.
- parameter_jacobian.col(j) -=
- Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
- }
- x_plus_delta(j) = x(j); // Restore x_plus_delta.
-
- // Divide out the run to get slope.
- parameter_jacobian.col(j) *= one_over_h;
- }
- return true;
-}
-
-class RuntimeNumericDiffCostFunction : public CostFunction {
- public:
- RuntimeNumericDiffCostFunction(const CostFunction* function,
- RuntimeNumericDiffMethod method,
- double relative_step_size)
- : function_(function),
- method_(method),
- relative_step_size_(relative_step_size) {
- *mutable_parameter_block_sizes() = function->parameter_block_sizes();
- set_num_residuals(function->num_residuals());
- }
-
- virtual ~RuntimeNumericDiffCostFunction() { }
-
- virtual bool Evaluate(double const* const* parameters,
- double* residuals,
- double** jacobians) const {
- // Get the function value (residuals) at the the point to evaluate.
- bool success = function_->Evaluate(parameters, residuals, NULL);
- if (!success) {
- // Something went wrong; ignore the jacobian.
- return false;
- }
- if (!jacobians) {
- // Nothing to do; just forward.
- return true;
- }
-
- const vector<int16>& block_sizes = function_->parameter_block_sizes();
- CHECK(!block_sizes.empty());
-
- // Create local space for a copy of the parameters which will get mutated.
- int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0);
- vector<double> parameters_copy(parameters_size);
- vector<double*> parameters_references_copy(block_sizes.size());
- parameters_references_copy[0] = &parameters_copy[0];
- for (int block = 1; block < block_sizes.size(); ++block) {
- parameters_references_copy[block] = parameters_references_copy[block - 1]
- + block_sizes[block - 1];
- }
-
- // Copy the parameters into the local temp space.
- for (int block = 0; block < block_sizes.size(); ++block) {
- memcpy(parameters_references_copy[block],
- parameters[block],
- block_sizes[block] * sizeof(*parameters[block]));
- }
-
- for (int block = 0; block < block_sizes.size(); ++block) {
- if (!jacobians[block]) {
- // No jacobian requested for this parameter / residual pair.
- continue;
- }
- if (!EvaluateJacobianForParameterBlock(function_,
- block_sizes[block],
- block,
- method_,
- relative_step_size_,
- residuals,
- &parameters_references_copy[0],
- jacobians)) {
- return false;
- }
- }
- return true;
- }
-
- private:
- const CostFunction* function_;
- RuntimeNumericDiffMethod method_;
- double relative_step_size_;
-};
-
-} // namespace
-
-CostFunction* CreateRuntimeNumericDiffCostFunction(
- const CostFunction* cost_function,
- RuntimeNumericDiffMethod method,
- double relative_step_size) {
- return new RuntimeNumericDiffCostFunction(cost_function,
- method,
- relative_step_size);
-}
-
-} // namespace internal
-} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h
deleted file mode 100644
index 01b57f92ef3..00000000000
--- a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
-// http://code.google.com/p/ceres-solver/
-//
-// 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: keir@google.com (Keir Mierle)
-//
-// Create CostFunctions as needed by the least squares framework with jacobians
-// computed via numeric differentiation.
-//
-// To get a numerically differentiated cost function, define a subclass of
-// CostFunction such that the Evaluate() function ignores the jacobian
-// parameter. The numeric differentiation wrapper will fill in the jacobian
-// parameter if nececssary by repeatedly calling the Evaluate() function with
-// small changes to the appropriate parameters, and computing the slope. This
-// implementation is not templated (hence the "Runtime" prefix), which is a bit
-// slower than but is more convenient than the templated version in
-// numeric_diff_cost_function.h
-//
-// The numerically differentiated version of a cost function for a cost function
-// can be constructed as follows:
-//
-// CostFunction* cost_function =
-// CreateRuntimeNumericDiffCostFunction(new MyCostFunction(...),
-// CENTRAL,
-// TAKE_OWNERSHIP);
-//
-// The central difference method is considerably more accurate; consider using
-// to start and only after that works, trying forward difference.
-//
-// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives.
-
-#ifndef CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_
-#define CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_
-
-#include "ceres/cost_function.h"
-
-namespace ceres {
-namespace internal {
-
-enum RuntimeNumericDiffMethod {
- CENTRAL,
- FORWARD,
-};
-
-// Create a cost function that evaluates the derivative with finite differences.
-// The base cost_function's implementation of Evaluate() only needs to fill in
-// the "residuals" argument and not the "jacobians". Any data written to the
-// jacobians by the base cost_function is overwritten.
-//
-// Forward difference or central difference is selected with CENTRAL or FORWARD.
-// The relative eps, which determines the step size for forward and central
-// differencing, is set with relative eps. Caller owns the resulting cost
-// function, and the resulting cost function does not own the base cost
-// function.
-CostFunction *CreateRuntimeNumericDiffCostFunction(
- const CostFunction *cost_function,
- RuntimeNumericDiffMethod method,
- double relative_eps);
-
-} // namespace internal
-} // namespace ceres
-
-#endif // CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
index b192aa1172b..2f407fdd260 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc
@@ -75,24 +75,19 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
fill(x, x + A->num_cols(), 0.0);
event_logger.AddEvent("Setup");
- LinearSolver::Summary summary;
- summary.num_iterations = 1;
- summary.termination_type = FAILURE;
eliminator_->Eliminate(A, b, per_solve_options.D, lhs_.get(), rhs_.get());
event_logger.AddEvent("Eliminate");
double* reduced_solution = x + A->num_cols() - lhs_->num_cols();
- const bool status = SolveReducedLinearSystem(reduced_solution);
+ const LinearSolver::Summary summary =
+ SolveReducedLinearSystem(reduced_solution);
event_logger.AddEvent("ReducedSolve");
- if (!status) {
- return summary;
+ if (summary.termination_type == LINEAR_SOLVER_SUCCESS) {
+ eliminator_->BackSubstitute(A, b, per_solve_options.D, reduced_solution, x);
+ event_logger.AddEvent("BackSubstitute");
}
- eliminator_->BackSubstitute(A, b, per_solve_options.D, reduced_solution, x);
- summary.termination_type = TOLERANCE;
-
- event_logger.AddEvent("BackSubstitute");
return summary;
}
@@ -117,7 +112,13 @@ void DenseSchurComplementSolver::InitStorage(
// Solve the system Sx = r, assuming that the matrix S is stored in a
// BlockRandomAccessDenseMatrix. The linear system is solved using
// Eigen's Cholesky factorization.
-bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+LinearSolver::Summary
+DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+ LinearSolver::Summary summary;
+ summary.num_iterations = 0;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+
const BlockRandomAccessDenseMatrix* m =
down_cast<const BlockRandomAccessDenseMatrix*>(lhs());
const int num_rows = m->num_rows();
@@ -125,25 +126,33 @@ bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
// The case where there are no f blocks, and the system is block
// diagonal.
if (num_rows == 0) {
- return true;
+ return summary;
}
+ summary.num_iterations = 1;
+
if (options().dense_linear_algebra_library_type == EIGEN) {
- // TODO(sameeragarwal): Add proper error handling; this completely ignores
- // the quality of the solution to the solve.
- VectorRef(solution, num_rows) =
+ Eigen::LLT<Matrix, Eigen::Upper> llt =
ConstMatrixRef(m->values(), num_rows, num_rows)
.selfadjointView<Eigen::Upper>()
- .llt()
- .solve(ConstVectorRef(rhs(), num_rows));
- return true;
+ .llt();
+ if (llt.info() != Eigen::Success) {
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = "Eigen LLT decomposition failed.";
+ return summary;
+ }
+
+ VectorRef(solution, num_rows) = llt.solve(ConstVectorRef(rhs(), num_rows));
+ } else {
+ VectorRef(solution, num_rows) = ConstVectorRef(rhs(), num_rows);
+ summary.termination_type =
+ LAPACK::SolveInPlaceUsingCholesky(num_rows,
+ m->values(),
+ solution,
+ &summary.message);
}
- VectorRef(solution, num_rows) = ConstVectorRef(rhs(), num_rows);
- const int info = LAPACK::SolveInPlaceUsingCholesky(num_rows,
- m->values(),
- solution);
- return (info == 0);
+ return summary;
}
#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE)
@@ -242,7 +251,8 @@ void SparseSchurComplementSolver::InitStorage(
set_rhs(new double[lhs()->num_rows()]);
}
-bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
switch (options().sparse_linear_algebra_library_type) {
case SUITE_SPARSE:
return SolveReducedLinearSystemUsingSuiteSparse(solution);
@@ -253,29 +263,33 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
<< options().sparse_linear_algebra_library_type;
}
- LOG(FATAL) << "Unknown sparse linear algebra library : "
- << options().sparse_linear_algebra_library_type;
- return false;
+ return LinearSolver::Summary();
}
#ifndef CERES_NO_SUITESPARSE
// Solve the system Sx = r, assuming that the matrix S is stored in a
// BlockRandomAccessSparseMatrix. The linear system is solved using
// CHOLMOD's sparse cholesky factorization routines.
-bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
double* solution) {
+ LinearSolver::Summary summary;
+ summary.num_iterations = 0;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+
TripletSparseMatrix* tsm =
const_cast<TripletSparseMatrix*>(
down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix());
-
const int num_rows = tsm->num_rows();
// The case where there are no f blocks, and the system is block
// diagonal.
if (num_rows == 0) {
- return true;
+ return summary;
}
+ summary.num_iterations = 1;
cholmod_sparse* cholmod_lhs = NULL;
if (options().use_postordering) {
// If we are going to do a full symbolic analysis of the schur
@@ -288,7 +302,10 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
cholmod_lhs->stype = 1;
if (factor_ == NULL) {
- factor_ = ss_.BlockAnalyzeCholesky(cholmod_lhs, blocks_, blocks_);
+ factor_ = ss_.BlockAnalyzeCholesky(cholmod_lhs,
+ blocks_,
+ blocks_,
+ &summary.message);
}
} else {
// If we are going to use the natural ordering (i.e. rely on the
@@ -301,33 +318,47 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
cholmod_lhs->stype = -1;
if (factor_ == NULL) {
- factor_ = ss_.AnalyzeCholeskyWithNaturalOrdering(cholmod_lhs);
+ factor_ = ss_.AnalyzeCholeskyWithNaturalOrdering(cholmod_lhs,
+ &summary.message);
}
}
+ if (factor_ == NULL) {
+ ss_.Free(cholmod_lhs);
+ summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;
+ return summary;
+ }
+
+ summary.termination_type =
+ ss_.Cholesky(cholmod_lhs, factor_, &summary.message);
+ if (summary.termination_type != LINEAR_SOLVER_SUCCESS) {
+ return summary;
+ }
+
cholmod_dense* cholmod_rhs =
ss_.CreateDenseVector(const_cast<double*>(rhs()), num_rows, num_rows);
- cholmod_dense* cholmod_solution =
- ss_.SolveCholesky(cholmod_lhs, factor_, cholmod_rhs);
-
+ cholmod_dense* cholmod_solution = ss_.Solve(factor_,
+ cholmod_rhs,
+ &summary.message);
ss_.Free(cholmod_lhs);
ss_.Free(cholmod_rhs);
if (cholmod_solution == NULL) {
- LOG(WARNING) << "CHOLMOD solve failed.";
- return false;
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ return summary;
}
VectorRef(solution, num_rows)
= VectorRef(static_cast<double*>(cholmod_solution->x), num_rows);
ss_.Free(cholmod_solution);
- return true;
+ return summary;
}
#else
-bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
double* solution) {
LOG(FATAL) << "No SuiteSparse support in Ceres.";
- return false;
+ return LinearSolver::Summary();
}
#endif // CERES_NO_SUITESPARSE
@@ -335,19 +366,24 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
// Solve the system Sx = r, assuming that the matrix S is stored in a
// BlockRandomAccessSparseMatrix. The linear system is solved using
// CXSparse's sparse cholesky factorization routines.
-bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
double* solution) {
+ LinearSolver::Summary summary;
+ summary.num_iterations = 0;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+
// Extract the TripletSparseMatrix that is used for actually storing S.
TripletSparseMatrix* tsm =
const_cast<TripletSparseMatrix*>(
down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix());
-
const int num_rows = tsm->num_rows();
// The case where there are no f blocks, and the system is block
// diagonal.
if (num_rows == 0) {
- return true;
+ return summary;
}
cs_di* lhs = CHECK_NOTNULL(cxsparse_.CreateSparseMatrix(tsm));
@@ -355,21 +391,27 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
// Compute symbolic factorization if not available.
if (cxsparse_factor_ == NULL) {
- cxsparse_factor_ =
- CHECK_NOTNULL(cxsparse_.BlockAnalyzeCholesky(lhs, blocks_, blocks_));
+ cxsparse_factor_ = cxsparse_.BlockAnalyzeCholesky(lhs, blocks_, blocks_);
}
- // Solve the linear system.
- bool ok = cxsparse_.SolveCholesky(lhs, cxsparse_factor_, solution);
+ if (cxsparse_factor_ == NULL) {
+ summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;
+ summary.message =
+ "CXSparse failure. Unable to find symbolic factorization.";
+ } else if (!cxsparse_.SolveCholesky(lhs, cxsparse_factor_, solution)) {
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
+ summary.message = "CXSparse::SolveCholesky failed.";
+ }
cxsparse_.Free(lhs);
- return ok;
+ return summary;
}
#else
-bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
+LinearSolver::Summary
+SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
double* solution) {
LOG(FATAL) << "No CXSparse support in Ceres.";
- return false;
+ return LinearSolver::Summary();
}
#endif // CERES_NO_CXPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
index b5a1c74ab1a..a9978518b17 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h
@@ -126,7 +126,8 @@ class SchurComplementSolver : public BlockSparseMatrixSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0;
- virtual bool SolveReducedLinearSystem(double* solution) = 0;
+ virtual LinearSolver::Summary SolveReducedLinearSystem(
+ double* solution) = 0;
LinearSolver::Options options_;
@@ -146,7 +147,8 @@ class DenseSchurComplementSolver : public SchurComplementSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs);
- virtual bool SolveReducedLinearSystem(double* solution);
+ virtual LinearSolver::Summary SolveReducedLinearSystem(
+ double* solution);
CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver);
};
@@ -160,9 +162,12 @@ class SparseSchurComplementSolver : public SchurComplementSolver {
private:
virtual void InitStorage(const CompressedRowBlockStructure* bs);
- virtual bool SolveReducedLinearSystem(double* solution);
- bool SolveReducedLinearSystemUsingSuiteSparse(double* solution);
- bool SolveReducedLinearSystemUsingCXSparse(double* solution);
+ virtual LinearSolver::Summary SolveReducedLinearSystem(
+ double* solution);
+ LinearSolver::Summary SolveReducedLinearSystemUsingSuiteSparse(
+ double* solution);
+ LinearSolver::Summary SolveReducedLinearSystemUsingCXSparse(
+ double* solution);
// Size of the blocks in the Schur complement.
vector<int> blocks_;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
index 31f83547b5f..25103dc542a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
@@ -37,7 +37,7 @@
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
-// This file is generated using generate_eliminator_specializations.py.
+// This file is generated using generate_eliminator_specialization.py.
// Editing it manually is not recommended.
#include "ceres/linear_solver.h"
@@ -105,6 +105,11 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
(options.f_block_size == Eigen::Dynamic)) {
return new SchurEliminator<2, 4, Eigen::Dynamic>(options);
}
+ if ((options.row_block_size == 2) &&
+ (options.e_block_size == Eigen::Dynamic) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<2, Eigen::Dynamic, Eigen::Dynamic>(options);
+ }
if ((options.row_block_size == 4) &&
(options.e_block_size == 4) &&
(options.f_block_size == 2)) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc
index 338df715c0a..6dc9e89d3cc 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc
@@ -33,10 +33,9 @@
#include <utility>
#include <vector>
#include "Eigen/Dense"
-#include "ceres/block_random_access_sparse_matrix.h"
+#include "ceres/block_random_access_diagonal_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/collections_port.h"
-#include "ceres/detect_structure.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/schur_eliminator.h"
@@ -57,16 +56,11 @@ SchurJacobiPreconditioner::SchurJacobiPreconditioner(
<< "SCHUR_JACOBI preconditioner.";
block_size_.resize(num_blocks);
- set<pair<int, int> > block_pairs;
-
- int num_block_diagonal_entries = 0;
for (int i = 0; i < num_blocks; ++i) {
block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size;
- block_pairs.insert(make_pair(i, i));
- num_block_diagonal_entries += block_size_[i] * block_size_[i];
}
- m_.reset(new BlockRandomAccessSparseMatrix(block_size_, block_pairs));
+ m_.reset(new BlockRandomAccessDiagonalMatrix(block_size_));
InitEliminator(bs);
}
@@ -77,17 +71,13 @@ SchurJacobiPreconditioner::~SchurJacobiPreconditioner() {
void SchurJacobiPreconditioner::InitEliminator(
const CompressedRowBlockStructure& bs) {
LinearSolver::Options eliminator_options;
-
eliminator_options.elimination_groups = options_.elimination_groups;
eliminator_options.num_threads = options_.num_threads;
-
- DetectStructure(bs, options_.elimination_groups[0],
- &eliminator_options.row_block_size,
- &eliminator_options.e_block_size,
- &eliminator_options.f_block_size);
-
+ eliminator_options.e_block_size = options_.e_block_size;
+ eliminator_options.f_block_size = options_.f_block_size;
+ eliminator_options.row_block_size = options_.row_block_size;
eliminator_.reset(SchurEliminatorBase::Create(eliminator_options));
- eliminator_->Init(options_.elimination_groups[0], &bs);
+ eliminator_->Init(eliminator_options.elimination_groups[0], &bs);
}
// Update the values of the preconditioner matrix and factorize it.
@@ -118,7 +108,7 @@ void SchurJacobiPreconditioner::RightMultiply(const double* x,
CHECK_NOTNULL(y);
const double* lhs_values =
- down_cast<BlockRandomAccessSparseMatrix*>(m_.get())->matrix()->values();
+ down_cast<BlockRandomAccessDiagonalMatrix*>(m_.get())->matrix()->values();
// This loop can be easily multi-threaded with OpenMP if need be.
for (int i = 0; i < block_size_.size(); ++i) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h
index f6e7b0d37ef..aecb0151083 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h
@@ -49,7 +49,7 @@
namespace ceres {
namespace internal {
-class BlockRandomAccessSparseMatrix;
+class BlockRandomAccessDiagonalMatrix;
class BlockSparseMatrix;
struct CompressedRowBlockStructure;
class SchurEliminatorBase;
@@ -100,7 +100,7 @@ class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner {
scoped_ptr<SchurEliminatorBase> eliminator_;
// Preconditioner matrix.
- scoped_ptr<BlockRandomAccessSparseMatrix> m_;
+ scoped_ptr<BlockRandomAccessDiagonalMatrix> m_;
CERES_DISALLOW_COPY_AND_ASSIGN(SchurJacobiPreconditioner);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc
new file mode 100644
index 00000000000..54b4379d5f2
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc
@@ -0,0 +1,107 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_NO_SUITESPARSE
+
+#include "ceres/single_linkage_clustering.h"
+
+#include "ceres/graph.h"
+#include "ceres/collections_port.h"
+#include "ceres/graph_algorithms.h"
+
+namespace ceres {
+namespace internal {
+
+int ComputeSingleLinkageClustering(
+ const SingleLinkageClusteringOptions& options,
+ const Graph<int>& graph,
+ HashMap<int, int>* membership) {
+ CHECK_NOTNULL(membership)->clear();
+
+ // Initially each vertex is in its own cluster.
+ const HashSet<int>& vertices = graph.vertices();
+ for (HashSet<int>::const_iterator it = vertices.begin();
+ it != vertices.end();
+ ++it) {
+ (*membership)[*it] = *it;
+ }
+
+ for (HashSet<int>::const_iterator it1 = vertices.begin();
+ it1 != vertices.end();
+ ++it1) {
+ const int vertex1 = *it1;
+ const HashSet<int>& neighbors = graph.Neighbors(vertex1);
+ for (HashSet<int>::const_iterator it2 = neighbors.begin();
+ it2 != neighbors.end();
+ ++it2) {
+ const int vertex2 = *it2;
+
+ // Since the graph is undirected, only pay attention to one side
+ // of the edge and ignore weak edges.
+ if ((vertex1 > vertex2) ||
+ (graph.EdgeWeight(vertex1, vertex2) < options.min_similarity)) {
+ continue;
+ }
+
+ // Use a union-find algorithm to keep track of the clusters.
+ const int c1 = FindConnectedComponent(vertex1, membership);
+ const int c2 = FindConnectedComponent(vertex2, membership);
+
+ if (c1 == c2) {
+ continue;
+ }
+
+ if (c1 < c2) {
+ (*membership)[c2] = c1;
+ } else {
+ (*membership)[c1] = c2;
+ }
+ }
+ }
+
+ // Make sure that every vertex is connected directly to the vertex
+ // identifying the cluster.
+ int num_clusters = 0;
+ for (HashMap<int, int>::iterator it = membership->begin();
+ it != membership->end();
+ ++it) {
+ it->second = FindConnectedComponent(it->first, membership);
+ if (it->first == it->second) {
+ ++num_clusters;
+ }
+ }
+
+ return num_clusters;
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_SUITESPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h
new file mode 100644
index 00000000000..9b137cfa67f
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h
@@ -0,0 +1,71 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_
+#define CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_
+
+#ifndef CERES_NO_SUITESPARSE
+
+#include "ceres/collections_port.h"
+#include "ceres/graph.h"
+
+namespace ceres {
+namespace internal {
+
+struct SingleLinkageClusteringOptions {
+ SingleLinkageClusteringOptions()
+ : min_similarity(0.99) {
+ }
+
+ // Graph edges with edge weight less than min_similarity are ignored
+ // during the clustering process.
+ double min_similarity;
+};
+
+// Compute a partitioning of the vertices of the graph using the
+// single linkage clustering algorithm. Edges with weight less than
+// SingleLinkageClusteringOptions::min_similarity will be ignored.
+//
+// membership upon return will contain a mapping from the vertices of
+// the graph to an integer indicating the identity of the cluster that
+// it belongs to.
+//
+// The return value of this function is the number of clusters
+// identified by the algorithm.
+int ComputeSingleLinkageClustering(
+ const SingleLinkageClusteringOptions& options,
+ const Graph<int>& graph,
+ HashMap<int, int>* membership);
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_SUITESPARSE
+#endif // CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
index 3b67746044c..67e168cd2d4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
@@ -86,6 +86,7 @@ Solver::Summary::Summary()
// accidentally reporting default values.
: minimizer_type(TRUST_REGION),
termination_type(DID_NOT_RUN),
+ error("ceres::Solve was not called."),
initial_cost(-1.0),
final_cost(-1.0),
fixed_cost(-1.0),
@@ -119,20 +120,20 @@ Solver::Summary::Summary()
inner_iterations_given(false),
inner_iterations_used(false),
preconditioner_type(IDENTITY),
+ visibility_clustering_type(CANONICAL_VIEWS),
trust_region_strategy_type(LEVENBERG_MARQUARDT),
dense_linear_algebra_library_type(EIGEN),
sparse_linear_algebra_library_type(SUITE_SPARSE),
line_search_direction_type(LBFGS),
- line_search_type(ARMIJO) {
+ line_search_type(ARMIJO),
+ line_search_interpolation_type(BISECTION),
+ nonlinear_conjugate_gradient_type(FLETCHER_REEVES),
+ max_lbfgs_rank(-1) {
}
string Solver::Summary::BriefReport() const {
string report = "Ceres Solver Report: ";
if (termination_type == DID_NOT_RUN) {
- CHECK(!error.empty())
- << "Solver terminated with DID_NOT_RUN but the solver did not "
- << "return a reason. This is a Ceres error. Please report this "
- << "to the Ceres team";
return report + "Termination: DID_NOT_RUN, because " + error;
}
@@ -237,6 +238,14 @@ string Solver::Summary::FullReport() const {
PreconditionerTypeToString(preconditioner_type));
}
+ if (preconditioner_type == CLUSTER_JACOBI ||
+ preconditioner_type == CLUSTER_TRIDIAGONAL) {
+ StringAppendF(&report, "Visibility clustering%24s%25s\n",
+ VisibilityClusteringTypeToString(
+ visibility_clustering_type),
+ VisibilityClusteringTypeToString(
+ visibility_clustering_type));
+ }
StringAppendF(&report, "Threads % 25d% 25d\n",
num_threads_given, num_threads_used);
StringAppendF(&report, "Linear solver threads % 23d% 25d\n",
@@ -306,10 +315,6 @@ string Solver::Summary::FullReport() const {
}
if (termination_type == DID_NOT_RUN) {
- CHECK(!error.empty())
- << "Solver terminated with DID_NOT_RUN but the solver did not "
- << "return a reason. This is a Ceres error. Please report this "
- << "to the Ceres team";
StringAppendF(&report, "Termination: %20s\n",
"DID_NOT_RUN");
StringAppendF(&report, "Reason: %s\n", error.c_str());
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
index 83faa0510c0..1ebf442131a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
@@ -454,6 +454,13 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
event_logger.AddEvent("ConstructOrdering");
}
+ if (original_options.inner_iteration_ordering != NULL) {
+ // Make a copy, as the options struct takes ownership of the
+ // ordering objects.
+ options.inner_iteration_ordering =
+ new ParameterBlockOrdering(*original_options.inner_iteration_ordering);
+ }
+
// Create the three objects needed to minimize: the transformed program, the
// evaluator, and the linear solver.
scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
@@ -494,6 +501,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
// Ensure the program state is set to the user parameters on the way out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ original_program->SetParameterOffsetsAndIndex();
summary->postprocessor_time_in_seconds =
WallTimeInSeconds() - post_process_start_time;
@@ -511,6 +519,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
summary->linear_solver_type_used = options.linear_solver_type;
summary->preconditioner_type = options.preconditioner_type;
+ summary->visibility_clustering_type = options.visibility_clustering_type;
summary->num_linear_solver_threads_given =
original_options.num_linear_solver_threads;
@@ -542,7 +551,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
<< "Disabling inner iterations.";
} else {
inner_iteration_minimizer.reset(
- CreateInnerIterationMinimizer(original_options,
+ CreateInnerIterationMinimizer(options,
*reduced_program,
problem_impl->parameter_map(),
summary));
@@ -596,6 +605,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
// Ensure the program state is set to the user parameters on the way
// out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ original_program->SetParameterOffsetsAndIndex();
const map<string, double>& linear_solver_time_statistics =
linear_solver->TimeStatistics();
@@ -839,6 +849,8 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
// Ensure the program state is set to the user parameters on the way out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ original_program->SetParameterOffsetsAndIndex();
+
summary->postprocessor_time_in_seconds =
WallTimeInSeconds() - post_process_start_time;
return;
@@ -889,6 +901,7 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
// Ensure the program state is set to the user parameters on the way out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ original_program->SetParameterOffsetsAndIndex();
const map<string, double>& evaluator_time_statistics =
evaluator->TimeStatistics();
@@ -968,14 +981,13 @@ bool SolverImpl::IsParameterBlockSetIndependent(
// Strips varying parameters and residuals, maintaining order, and updating
-// num_eliminate_blocks.
-bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
- ParameterBlockOrdering* ordering,
- double* fixed_cost,
- string* error) {
- vector<ParameterBlock*>* parameter_blocks =
- program->mutable_parameter_blocks();
-
+// orderings.
+bool SolverImpl::RemoveFixedBlocksFromProgram(
+ Program* program,
+ ParameterBlockOrdering* linear_solver_ordering,
+ ParameterBlockOrdering* inner_iteration_ordering,
+ double* fixed_cost,
+ string* error) {
scoped_array<double> residual_block_evaluate_scratch;
if (fixed_cost != NULL) {
residual_block_evaluate_scratch.reset(
@@ -983,70 +995,79 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
*fixed_cost = 0.0;
}
- // Mark all the parameters as unused. Abuse the index member of the parameter
- // blocks for the marking.
+ vector<ParameterBlock*>* parameter_blocks =
+ program->mutable_parameter_blocks();
+ vector<ResidualBlock*>* residual_blocks =
+ program->mutable_residual_blocks();
+
+ // Mark all the parameters as unused. Abuse the index member of the
+ // parameter blocks for the marking.
for (int i = 0; i < parameter_blocks->size(); ++i) {
(*parameter_blocks)[i]->set_index(-1);
}
// Filter out residual that have all-constant parameters, and mark all the
// parameter blocks that appear in residuals.
- {
- vector<ResidualBlock*>* residual_blocks =
- program->mutable_residual_blocks();
- int j = 0;
- for (int i = 0; i < residual_blocks->size(); ++i) {
- ResidualBlock* residual_block = (*residual_blocks)[i];
- int num_parameter_blocks = residual_block->NumParameterBlocks();
-
- // Determine if the residual block is fixed, and also mark varying
- // parameters that appear in the residual block.
- bool all_constant = true;
- for (int k = 0; k < num_parameter_blocks; k++) {
- ParameterBlock* parameter_block = residual_block->parameter_blocks()[k];
- if (!parameter_block->IsConstant()) {
- all_constant = false;
- parameter_block->set_index(1);
- }
+ int num_active_residual_blocks = 0;
+ for (int i = 0; i < residual_blocks->size(); ++i) {
+ ResidualBlock* residual_block = (*residual_blocks)[i];
+ int num_parameter_blocks = residual_block->NumParameterBlocks();
+
+ // Determine if the residual block is fixed, and also mark varying
+ // parameters that appear in the residual block.
+ bool all_constant = true;
+ for (int k = 0; k < num_parameter_blocks; k++) {
+ ParameterBlock* parameter_block = residual_block->parameter_blocks()[k];
+ if (!parameter_block->IsConstant()) {
+ all_constant = false;
+ parameter_block->set_index(1);
}
+ }
- if (!all_constant) {
- (*residual_blocks)[j++] = (*residual_blocks)[i];
- } else if (fixed_cost != NULL) {
- // The residual is constant and will be removed, so its cost is
- // added to the variable fixed_cost.
- double cost = 0.0;
- if (!residual_block->Evaluate(true,
- &cost,
- NULL,
- NULL,
- residual_block_evaluate_scratch.get())) {
- *error = StringPrintf("Evaluation of the residual %d failed during "
- "removal of fixed residual blocks.", i);
- return false;
- }
- *fixed_cost += cost;
+ if (!all_constant) {
+ (*residual_blocks)[num_active_residual_blocks++] = residual_block;
+ } else if (fixed_cost != NULL) {
+ // The residual is constant and will be removed, so its cost is
+ // added to the variable fixed_cost.
+ double cost = 0.0;
+ if (!residual_block->Evaluate(true,
+ &cost,
+ NULL,
+ NULL,
+ residual_block_evaluate_scratch.get())) {
+ *error = StringPrintf("Evaluation of the residual %d failed during "
+ "removal of fixed residual blocks.", i);
+ return false;
}
+ *fixed_cost += cost;
}
- residual_blocks->resize(j);
- }
-
- // Filter out unused or fixed parameter blocks, and update
- // the ordering.
- {
- vector<ParameterBlock*>* parameter_blocks =
- program->mutable_parameter_blocks();
- int j = 0;
- for (int i = 0; i < parameter_blocks->size(); ++i) {
- ParameterBlock* parameter_block = (*parameter_blocks)[i];
- if (parameter_block->index() == 1) {
- (*parameter_blocks)[j++] = parameter_block;
- } else {
- ordering->Remove(parameter_block->mutable_user_state());
+ }
+ residual_blocks->resize(num_active_residual_blocks);
+
+ // Filter out unused or fixed parameter blocks, and update the
+ // linear_solver_ordering and the inner_iteration_ordering (if
+ // present).
+ int num_active_parameter_blocks = 0;
+ for (int i = 0; i < parameter_blocks->size(); ++i) {
+ ParameterBlock* parameter_block = (*parameter_blocks)[i];
+ if (parameter_block->index() == -1) {
+ // Parameter block is constant.
+ if (linear_solver_ordering != NULL) {
+ linear_solver_ordering->Remove(parameter_block->mutable_user_state());
+ }
+
+ // It is not necessary that the inner iteration ordering contain
+ // this parameter block. But calling Remove is safe, as it will
+ // just return false.
+ if (inner_iteration_ordering != NULL) {
+ inner_iteration_ordering->Remove(parameter_block->mutable_user_state());
}
+ continue;
}
- parameter_blocks->resize(j);
+
+ (*parameter_blocks)[num_active_parameter_blocks++] = parameter_block;
}
+ parameter_blocks->resize(num_active_parameter_blocks);
if (!(((program->NumResidualBlocks() == 0) &&
(program->NumParameterBlocks() == 0)) ||
@@ -1071,9 +1092,11 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
options->linear_solver_ordering;
const int min_group_id =
linear_solver_ordering->group_to_elements().begin()->first;
-
+ ParameterBlockOrdering* inner_iteration_ordering =
+ options->inner_iteration_ordering;
if (!RemoveFixedBlocksFromProgram(transformed_program.get(),
linear_solver_ordering,
+ inner_iteration_ordering,
fixed_cost,
error)) {
return NULL;
@@ -1239,6 +1262,8 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
options->max_linear_solver_iterations;
linear_solver_options.type = options->linear_solver_type;
linear_solver_options.preconditioner_type = options->preconditioner_type;
+ linear_solver_options.visibility_clustering_type =
+ options->visibility_clustering_type;
linear_solver_options.sparse_linear_algebra_library_type =
options->sparse_linear_algebra_library_type;
linear_solver_options.dense_linear_algebra_library_type =
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
index 2b7ca3e3310..aef63b044dd 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
@@ -120,15 +120,24 @@ class SolverImpl {
string* error);
// Remove the fixed or unused parameter blocks and residuals
- // depending only on fixed parameters from the problem. Also updates
- // num_eliminate_blocks, since removed parameters changes the point
- // at which the eliminated blocks is valid. If fixed_cost is not
- // NULL, the residual blocks that are removed are evaluated and the
- // sum of their cost is returned in fixed_cost.
- static bool RemoveFixedBlocksFromProgram(Program* program,
- ParameterBlockOrdering* ordering,
- double* fixed_cost,
- string* error);
+ // depending only on fixed parameters from the program.
+ //
+ // If either linear_solver_ordering or inner_iteration_ordering are
+ // not NULL, the constant parameter blocks are removed from them
+ // too.
+ //
+ // If fixed_cost is not NULL, the residual blocks that are removed
+ // are evaluated and the sum of their cost is returned in
+ // fixed_cost.
+ //
+ // If a failure is encountered, the function returns false with a
+ // description of the failure in error.
+ static bool RemoveFixedBlocksFromProgram(
+ Program* program,
+ ParameterBlockOrdering* linear_solver_ordering,
+ ParameterBlockOrdering* inner_iteration_ordering,
+ double* fixed_cost,
+ string* error);
static bool IsOrderingValid(const Solver::Options& options,
const ProblemImpl* problem_impl,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
index f1a52378e2b..1ead8f70ae2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -102,6 +102,9 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
LinearSolver::Summary summary;
summary.num_iterations = 1;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.message = "Success.";
+
const int num_cols = A->num_cols();
Vector Atb = Vector::Zero(num_cols);
A->LeftMultiply(b, Atb.data());
@@ -137,21 +140,23 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
// Compute symbolic factorization if not available.
if (cxsparse_factor_ == NULL) {
if (options_.use_postordering) {
- cxsparse_factor_ =
- CHECK_NOTNULL(cxsparse_.BlockAnalyzeCholesky(AtA,
- A->col_blocks(),
- A->col_blocks()));
+ cxsparse_factor_ = cxsparse_.BlockAnalyzeCholesky(AtA,
+ A->col_blocks(),
+ A->col_blocks());
} else {
- cxsparse_factor_ =
- CHECK_NOTNULL(cxsparse_.AnalyzeCholeskyWithNaturalOrdering(AtA));
+ cxsparse_factor_ = cxsparse_.AnalyzeCholeskyWithNaturalOrdering(AtA);
}
}
event_logger.AddEvent("Analysis");
- // Solve the linear system.
- if (cxsparse_.SolveCholesky(AtA, cxsparse_factor_, Atb.data())) {
+ if (cxsparse_factor_ == NULL) {
+ summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;
+ summary.message =
+ "CXSparse failure. Unable to find symbolic factorization.";
+ } else if (cxsparse_.SolveCholesky(AtA, cxsparse_factor_, Atb.data())) {
VectorRef(x, Atb.rows()) = Atb;
- summary.termination_type = TOLERANCE;
+ } else {
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
}
event_logger.AddEvent("Solve");
@@ -179,56 +184,68 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
const LinearSolver::PerSolveOptions& per_solve_options,
double * x) {
EventLogger event_logger("SparseNormalCholeskySolver::SuiteSparse::Solve");
+ LinearSolver::Summary summary;
+ summary.termination_type = LINEAR_SOLVER_SUCCESS;
+ summary.num_iterations = 1;
+ summary.message = "Success.";
const int num_cols = A->num_cols();
- LinearSolver::Summary summary;
Vector Atb = Vector::Zero(num_cols);
A->LeftMultiply(b, Atb.data());
if (per_solve_options.D != NULL) {
- // Temporarily append a diagonal block to the A matrix, but undo it before
- // returning the matrix to the user.
+ // Temporarily append a diagonal block to the A matrix, but undo
+ // it before returning the matrix to the user.
CompressedRowSparseMatrix D(per_solve_options.D, num_cols);
A->AppendRows(D);
}
VectorRef(x, num_cols).setZero();
-
cholmod_sparse lhs = ss_.CreateSparseMatrixTransposeView(A);
- cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols);
event_logger.AddEvent("Setup");
if (factor_ == NULL) {
if (options_.use_postordering) {
- factor_ =
- CHECK_NOTNULL(ss_.BlockAnalyzeCholesky(&lhs,
- A->col_blocks(),
- A->row_blocks()));
+ factor_ = ss_.BlockAnalyzeCholesky(&lhs,
+ A->col_blocks(),
+ A->row_blocks(),
+ &summary.message);
} else {
- factor_ =
- CHECK_NOTNULL(ss_.AnalyzeCholeskyWithNaturalOrdering(&lhs));
+ factor_ = ss_.AnalyzeCholeskyWithNaturalOrdering(&lhs, &summary.message);
}
}
-
event_logger.AddEvent("Analysis");
- cholmod_dense* sol = ss_.SolveCholesky(&lhs, factor_, rhs);
+ if (factor_ == NULL) {
+ if (per_solve_options.D != NULL) {
+ A->DeleteRows(num_cols);
+ }
+ summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;
+ return summary;
+ }
+
+ summary.termination_type = ss_.Cholesky(&lhs, factor_, &summary.message);
+ if (summary.termination_type != LINEAR_SOLVER_SUCCESS) {
+ if (per_solve_options.D != NULL) {
+ A->DeleteRows(num_cols);
+ }
+ return summary;
+ }
+
+ cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols);
+ cholmod_dense* sol = ss_.Solve(factor_, rhs, &summary.message);
event_logger.AddEvent("Solve");
ss_.Free(rhs);
- rhs = NULL;
-
if (per_solve_options.D != NULL) {
A->DeleteRows(num_cols);
}
- summary.num_iterations = 1;
if (sol != NULL) {
memcpy(x, sol->x, num_cols * sizeof(*x));
-
ss_.Free(sol);
- sol = NULL;
- summary.termination_type = TOLERANCE;
+ } else {
+ summary.termination_type = LINEAR_SOLVER_FAILURE;
}
event_logger.AddEvent("Teardown");
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
index ce204674dce..eabdcb697c9 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
@@ -43,7 +43,7 @@ namespace internal {
#ifdef _MSC_VER
enum { IS_COMPILER_MSVC = 1 };
-#define va_copy(d,s) ((d) = (s))
+#define va_copy(d, s) ((d) = (s))
#else
enum { IS_COMPILER_MSVC = 0 };
#endif
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
index 9de32fd76ad..06cc0a8e6fa 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
@@ -35,6 +35,7 @@
#include "cholmod.h"
#include "ceres/compressed_col_sparse_matrix_utils.h"
#include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/linear_solver.h"
#include "ceres/triplet_sparse_matrix.h"
namespace ceres {
@@ -120,7 +121,8 @@ cholmod_dense* SuiteSparse::CreateDenseVector(const double* x,
return v;
}
-cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) {
+cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A,
+ string* status) {
// Cholmod can try multiple re-ordering strategies to find a fill
// reducing ordering. Here we just tell it use AMD with automatic
// matrix dependence choice of supernodal versus simplicial
@@ -130,31 +132,35 @@ cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) {
cc_.supernodal = CHOLMOD_AUTO;
cholmod_factor* factor = cholmod_analyze(A, &cc_);
- CHECK_EQ(cc_.status, CHOLMOD_OK)
- << "Cholmod symbolic analysis failed " << cc_.status;
- CHECK_NOTNULL(factor);
-
if (VLOG_IS_ON(2)) {
cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
}
- return factor;
+ if (cc_.status != CHOLMOD_OK) {
+ *status = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
+ return NULL;
+ }
+
+ return CHECK_NOTNULL(factor);
}
cholmod_factor* SuiteSparse::BlockAnalyzeCholesky(
cholmod_sparse* A,
const vector<int>& row_blocks,
- const vector<int>& col_blocks) {
+ const vector<int>& col_blocks,
+ string* status) {
vector<int> ordering;
if (!BlockAMDOrdering(A, row_blocks, col_blocks, &ordering)) {
return NULL;
}
- return AnalyzeCholeskyWithUserOrdering(A, ordering);
+ return AnalyzeCholeskyWithUserOrdering(A, ordering, status);
}
cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
cholmod_sparse* A,
- const vector<int>& ordering) {
+ const vector<int>& ordering,
+ string* status) {
CHECK_EQ(ordering.size(), A->nrow);
cc_.nmethods = 1;
@@ -162,33 +168,36 @@ cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
cholmod_factor* factor =
cholmod_analyze_p(A, const_cast<int*>(&ordering[0]), NULL, 0, &cc_);
- CHECK_EQ(cc_.status, CHOLMOD_OK)
- << "Cholmod symbolic analysis failed " << cc_.status;
- CHECK_NOTNULL(factor);
-
if (VLOG_IS_ON(2)) {
cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
}
+ if (cc_.status != CHOLMOD_OK) {
+ *status = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
+ return NULL;
+ }
- return factor;
+ return CHECK_NOTNULL(factor);
}
cholmod_factor* SuiteSparse::AnalyzeCholeskyWithNaturalOrdering(
- cholmod_sparse* A) {
+ cholmod_sparse* A,
+ string* status) {
cc_.nmethods = 1;
cc_.method[0].ordering = CHOLMOD_NATURAL;
cc_.postorder = 0;
cholmod_factor* factor = cholmod_analyze(A, &cc_);
- CHECK_EQ(cc_.status, CHOLMOD_OK)
- << "Cholmod symbolic analysis failed " << cc_.status;
- CHECK_NOTNULL(factor);
-
if (VLOG_IS_ON(2)) {
cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
}
+ if (cc_.status != CHOLMOD_OK) {
+ *status = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
+ return NULL;
+ }
- return factor;
+ return CHECK_NOTNULL(factor);
}
bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A,
@@ -233,7 +242,9 @@ bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A,
return true;
}
-bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) {
+LinearSolverTerminationType SuiteSparse::Cholesky(cholmod_sparse* A,
+ cholmod_factor* L,
+ string* status) {
CHECK_NOTNULL(A);
CHECK_NOTNULL(L);
@@ -245,7 +256,7 @@ bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) {
cc_.print = 0;
cc_.quick_return_if_not_posdef = 1;
- int status = cholmod_factorize(A, L, &cc_);
+ int cholmod_status = cholmod_factorize(A, L, &cc_);
cc_.print = old_print_level;
// TODO(sameeragarwal): This switch statement is not consistent. It
@@ -257,84 +268,73 @@ bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) {
// (e.g. out of memory).
switch (cc_.status) {
case CHOLMOD_NOT_INSTALLED:
- LOG(WARNING) << "CHOLMOD failure: Method not installed.";
- return false;
+ *status = "CHOLMOD failure: Method not installed.";
+ return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_OUT_OF_MEMORY:
- LOG(WARNING) << "CHOLMOD failure: Out of memory.";
- return false;
+ *status = "CHOLMOD failure: Out of memory.";
+ return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_TOO_LARGE:
- LOG(WARNING) << "CHOLMOD failure: Integer overflow occured.";
- return false;
+ *status = "CHOLMOD failure: Integer overflow occured.";
+ return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_INVALID:
- LOG(WARNING) << "CHOLMOD failure: Invalid input.";
- return false;
+ *status = "CHOLMOD failure: Invalid input.";
+ return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_NOT_POSDEF:
- // TODO(sameeragarwal): These two warnings require more
- // sophisticated handling going forward. For now we will be
- // strict and treat them as failures.
- LOG(WARNING) << "CHOLMOD warning: Matrix not positive definite.";
- return false;
+ *status = "CHOLMOD warning: Matrix not positive definite.";
+ return LINEAR_SOLVER_FAILURE;
case CHOLMOD_DSMALL:
- LOG(WARNING) << "CHOLMOD warning: D for LDL' or diag(L) or "
- << "LL' has tiny absolute value.";
- return false;
+ *status = "CHOLMOD warning: D for LDL' or diag(L) or "
+ "LL' has tiny absolute value.";
+ return LINEAR_SOLVER_FAILURE;
case CHOLMOD_OK:
- if (status != 0) {
- return true;
+ if (cholmod_status != 0) {
+ return LINEAR_SOLVER_SUCCESS;
}
- LOG(WARNING) << "CHOLMOD failure: cholmod_factorize returned zero "
- << "but cholmod_common::status is CHOLMOD_OK."
- << "Please report this to ceres-solver@googlegroups.com.";
- return false;
+
+ *status = "CHOLMOD failure: cholmod_factorize returned false "
+ "but cholmod_common::status is CHOLMOD_OK."
+ "Please report this to ceres-solver@googlegroups.com.";
+ return LINEAR_SOLVER_FATAL_ERROR;
default:
- LOG(WARNING) << "Unknown cholmod return code. "
- << "Please report this to ceres-solver@googlegroups.com.";
- return false;
+ *status =
+ StringPrintf("Unknown cholmod return code: %d. "
+ "Please report this to ceres-solver@googlegroups.com.",
+ cc_.status);
+ return LINEAR_SOLVER_FATAL_ERROR;
}
- return false;
+
+ return LINEAR_SOLVER_FATAL_ERROR;
}
cholmod_dense* SuiteSparse::Solve(cholmod_factor* L,
- cholmod_dense* b) {
+ cholmod_dense* b,
+ string* status) {
if (cc_.status != CHOLMOD_OK) {
- LOG(WARNING) << "CHOLMOD status NOT OK";
+ *status = "cholmod_solve failed. CHOLMOD status is not CHOLMOD_OK";
return NULL;
}
return cholmod_solve(CHOLMOD_A, L, b, &cc_);
}
-cholmod_dense* SuiteSparse::SolveCholesky(cholmod_sparse* A,
- cholmod_factor* L,
- cholmod_dense* b) {
- CHECK_NOTNULL(A);
- CHECK_NOTNULL(L);
- CHECK_NOTNULL(b);
-
- if (Cholesky(A, L)) {
- return Solve(L, b);
- }
-
- return NULL;
-}
-
-void SuiteSparse::ApproximateMinimumDegreeOrdering(cholmod_sparse* matrix,
+bool SuiteSparse::ApproximateMinimumDegreeOrdering(cholmod_sparse* matrix,
int* ordering) {
- cholmod_amd(matrix, NULL, 0, ordering, &cc_);
+ return cholmod_amd(matrix, NULL, 0, ordering, &cc_);
}
-void SuiteSparse::ConstrainedApproximateMinimumDegreeOrdering(
+bool SuiteSparse::ConstrainedApproximateMinimumDegreeOrdering(
cholmod_sparse* matrix,
int* constraints,
int* ordering) {
#ifndef CERES_NO_CAMD
- cholmod_camd(matrix, NULL, 0, constraints, ordering, &cc_);
+ return cholmod_camd(matrix, NULL, 0, constraints, ordering, &cc_);
#else
LOG(FATAL) << "Congratulations you have found a bug in Ceres."
<< "Ceres Solver was compiled with SuiteSparse "
<< "version 4.1.0 or less. Calling this function "
<< "in that case is a bug. Please contact the"
<< "the Ceres Solver developers.";
+ return false;
#endif
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
index 16f298ea79c..0604654f7c8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
@@ -41,6 +41,7 @@
#include <vector>
#include "ceres/internal/port.h"
+#include "ceres/linear_solver.h"
#include "cholmod.h"
#include "glog/logging.h"
#include "SuiteSparseQR.hpp"
@@ -138,12 +139,15 @@ class SuiteSparse {
// A is not modified, only the pattern of non-zeros of A is used,
// the actual numerical values in A are of no consequence.
//
+ // status contains an explanation of the failures if any.
+ //
// Caller owns the result.
- cholmod_factor* AnalyzeCholesky(cholmod_sparse* A);
+ cholmod_factor* AnalyzeCholesky(cholmod_sparse* A, string* status);
cholmod_factor* BlockAnalyzeCholesky(cholmod_sparse* A,
const vector<int>& row_blocks,
- const vector<int>& col_blocks);
+ const vector<int>& col_blocks,
+ string* status);
// If A is symmetric, then compute the symbolic Cholesky
// factorization of A(ordering, ordering). If A is unsymmetric, then
@@ -153,33 +157,38 @@ class SuiteSparse {
// A is not modified, only the pattern of non-zeros of A is used,
// the actual numerical values in A are of no consequence.
//
+ // status contains an explanation of the failures if any.
+ //
// Caller owns the result.
cholmod_factor* AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
- const vector<int>& ordering);
+ const vector<int>& ordering,
+ string* status);
// Perform a symbolic factorization of A without re-ordering A. No
// postordering of the elimination tree is performed. This ensures
// that the symbolic factor does not introduce an extra permutation
// on the matrix. See the documentation for CHOLMOD for more details.
- cholmod_factor* AnalyzeCholeskyWithNaturalOrdering(cholmod_sparse* A);
+ //
+ // status contains an explanation of the failures if any.
+ cholmod_factor* AnalyzeCholeskyWithNaturalOrdering(cholmod_sparse* A,
+ string* status);
// Use the symbolic factorization in L, to find the numerical
// factorization for the matrix A or AA^T. Return true if
// successful, false otherwise. L contains the numeric factorization
// on return.
- bool Cholesky(cholmod_sparse* A, cholmod_factor* L);
+ //
+ // status contains an explanation of the failures if any.
+ LinearSolverTerminationType Cholesky(cholmod_sparse* A,
+ cholmod_factor* L,
+ string* status);
// Given a Cholesky factorization of a matrix A = LL^T, solve the
// linear system Ax = b, and return the result. If the Solve fails
// NULL is returned. Caller owns the result.
- cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b);
-
- // Combine the calls to Cholesky and Solve into a single call. If
- // the cholesky factorization or the solve fails, return
- // NULL. Caller owns the result.
- cholmod_dense* SolveCholesky(cholmod_sparse* A,
- cholmod_factor* L,
- cholmod_dense* b);
+ //
+ // status contains an explanation of the failures if any.
+ cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b, string* solve);
// By virtue of the modeling layer in Ceres being block oriented,
// all the matrices used by Ceres are also block oriented. When
@@ -211,7 +220,7 @@ class SuiteSparse {
// Find a fill reducing approximate minimum degree
// ordering. ordering is expected to be large enough to hold the
// ordering.
- void ApproximateMinimumDegreeOrdering(cholmod_sparse* matrix, int* ordering);
+ bool ApproximateMinimumDegreeOrdering(cholmod_sparse* matrix, int* ordering);
// Before SuiteSparse version 4.2.0, cholmod_camd was only enabled
@@ -241,7 +250,7 @@ class SuiteSparse {
//
// If CERES_NO_CAMD is defined then calling this function will
// result in a crash.
- void ConstrainedApproximateMinimumDegreeOrdering(cholmod_sparse* matrix,
+ bool ConstrainedApproximateMinimumDegreeOrdering(cholmod_sparse* matrix,
int* constraints,
int* ordering);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
index 03d6c8e6b94..a613a655559 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
@@ -81,6 +81,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
double start_time = WallTimeInSeconds();
double iteration_start_time = start_time;
Init(options);
+ const bool is_not_silent = !options.is_silent;
summary->termination_type = NO_CONVERGENCE;
summary->num_successful_steps = 0;
@@ -112,11 +113,10 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.step_is_successful = false;
iteration_summary.cost_change = 0.0;
iteration_summary.gradient_max_norm = 0.0;
+ iteration_summary.gradient_norm = 0.0;
iteration_summary.step_norm = 0.0;
iteration_summary.relative_decrease = 0.0;
iteration_summary.trust_region_radius = strategy->Radius();
- // TODO(sameeragarwal): Rename eta to linear_solver_accuracy or
- // something similar across the board.
iteration_summary.eta = options_.eta;
iteration_summary.linear_solver_iterations = 0;
iteration_summary.step_solver_time_in_seconds = 0;
@@ -128,8 +128,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
residuals.data(),
gradient.data(),
jacobian)) {
- LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed.";
+ summary->error = "Terminating: Residual and Jacobian evaluation failed.";
summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
return;
}
@@ -143,6 +144,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
summary->initial_cost = cost + summary->fixed_cost;
iteration_summary.cost = cost + summary->fixed_cost;
iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
+ iteration_summary.gradient_norm = gradient.norm();
// The initial gradient max_norm is bounded from below so that we do
// not divide by zero.
@@ -152,11 +154,13 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
options_.gradient_tolerance * initial_gradient_max_norm;
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->error = StringPrintf("Terminating: Gradient tolerance reached. "
+ "Relative gradient max norm: %e <= %e",
+ (iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm),
+ options_.gradient_tolerance);
summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating: Gradient tolerance reached."
- << "Relative gradient max norm: "
- << iteration_summary.gradient_max_norm / initial_gradient_max_norm
- << " <= " << options_.gradient_tolerance;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
@@ -184,17 +188,19 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_start_time = WallTimeInSeconds();
if (iteration_summary.iteration >= options_.max_num_iterations) {
+ summary->error = "Terminating: Maximum number of iterations reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG(1) << "Terminating: Maximum number of iterations reached.";
- break;
+ VLOG_IF(1, is_not_silent) << summary->error;
+ return;
}
const double total_solver_time = iteration_start_time - start_time +
summary->preprocessor_time_in_seconds;
if (total_solver_time >= options_.max_solver_time_in_seconds) {
+ summary->error = "Terminating: Maximum solver time reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG(1) << "Terminating: Maximum solver time reached.";
- break;
+ VLOG_IF(1, is_not_silent) << summary->error;
+ return;
}
const double strategy_start_time = WallTimeInSeconds();
@@ -221,6 +227,15 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
residuals.data(),
trust_region_step.data());
+ if (strategy_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
+ summary->error =
+ "Terminating. Linear solver failed due to unrecoverable "
+ "non-numeric causes. Please see the error log for clues. ";
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
+ return;
+ }
+
iteration_summary = IterationSummary();
iteration_summary.iteration = summary->iterations.back().iteration + 1;
iteration_summary.step_solver_time_in_seconds =
@@ -230,8 +245,17 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.step_is_valid = false;
iteration_summary.step_is_successful = false;
+ if (strategy_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
+ summary->error =
+ "Terminating. Linear solver failed due to unrecoverable "
+ "non-numeric causes. Please see the error log for clues. ";
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
+ return;
+ }
+
double model_cost_change = 0.0;
- if (strategy_summary.termination_type != FAILURE) {
+ if (strategy_summary.termination_type != LINEAR_SOLVER_FAILURE) {
// new_model_cost
// = 1/2 [f + J * step]^2
// = 1/2 [ f'f + 2f'J * step + step' * J' * J * step ]
@@ -245,9 +269,10 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
- model_residuals.dot(residuals + model_residuals / 2.0);
if (model_cost_change < 0.0) {
- VLOG(1) << "Invalid step: current_cost: " << cost
- << " absolute difference " << model_cost_change
- << " relative difference " << (model_cost_change / cost);
+ VLOG_IF(1, is_not_silent)
+ << "Invalid step: current_cost: " << cost
+ << " absolute difference " << model_cost_change
+ << " relative difference " << (model_cost_change / cost);
} else {
iteration_summary.step_is_valid = true;
}
@@ -259,13 +284,12 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// NUMERICAL_FAILURE if this limit is exceeded.
if (++num_consecutive_invalid_steps >=
options_.max_num_consecutive_invalid_steps) {
- summary->termination_type = NUMERICAL_FAILURE;
summary->error = StringPrintf(
"Terminating. Number of successive invalid steps more "
"than Solver::Options::max_num_consecutive_invalid_steps: %d",
options_.max_num_consecutive_invalid_steps);
-
- LOG(WARNING) << summary->error;
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
return;
}
@@ -278,6 +302,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.cost_change = 0.0;
iteration_summary.gradient_max_norm =
summary->iterations.back().gradient_max_norm;
+ iteration_summary.gradient_norm =
+ summary->iterations.back().gradient_norm;
iteration_summary.step_norm = 0.0;
iteration_summary.relative_decrease = 0.0;
iteration_summary.eta = options_.eta;
@@ -287,24 +313,18 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// Undo the Jacobian column scaling.
delta = (trust_region_step.array() * scale.array()).matrix();
- if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) {
- summary->termination_type = NUMERICAL_FAILURE;
- summary->error =
- "Terminating. Failed to compute Plus(x, delta, x_plus_delta).";
-
- LOG(WARNING) << summary->error;
- return;
- }
- // Try this step.
double new_cost = numeric_limits<double>::max();
- if (!evaluator->Evaluate(x_plus_delta.data(),
- &new_cost,
- NULL, NULL, NULL)) {
- // If the evaluation of the new cost fails, treat it as a step
- // with high cost.
+ if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) {
+ LOG(WARNING) << "x_plus_delta = Plus(x, delta) failed. "
+ << "Treating it as a step with infinite cost";
+ } else if (!evaluator->Evaluate(x_plus_delta.data(),
+ &new_cost,
+ NULL,
+ NULL,
+ NULL)) {
LOG(WARNING) << "Step failed to evaluate. "
- << "Treating it as step with infinite cost";
+ << "Treating it as a step with infinite cost";
new_cost = numeric_limits<double>::max();
} else {
// Check if performing an inner iteration will make it better.
@@ -320,30 +340,30 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
if (!evaluator->Evaluate(inner_iteration_x.data(),
&new_cost,
NULL, NULL, NULL)) {
- VLOG(2) << "Inner iteration failed.";
+ VLOG_IF(2, is_not_silent) << "Inner iteration failed.";
new_cost = x_plus_delta_cost;
} else {
x_plus_delta = inner_iteration_x;
// Boost the model_cost_change, since the inner iteration
// improvements are not accounted for by the trust region.
model_cost_change += x_plus_delta_cost - new_cost;
- VLOG(2) << "Inner iteration succeeded; current cost: " << cost
- << " x_plus_delta_cost: " << x_plus_delta_cost
- << " new_cost: " << new_cost;
- const double inner_iteration_relative_progress =
- 1.0 - new_cost / x_plus_delta_cost;
- inner_iterations_are_enabled =
- (inner_iteration_relative_progress >
- options.inner_iteration_tolerance);
+ VLOG_IF(2, is_not_silent)
+ << "Inner iteration succeeded; Current cost: " << cost
+ << " Trust region step cost: " << x_plus_delta_cost
+ << " Inner iteration cost: " << new_cost;
inner_iterations_were_useful = new_cost < cost;
+ const double inner_iteration_relative_progress =
+ 1.0 - new_cost / x_plus_delta_cost;
// Disable inner iterations once the relative improvement
// drops below tolerance.
- if (!inner_iterations_are_enabled) {
- VLOG(2) << "Disabling inner iterations. Progress : "
- << inner_iteration_relative_progress;
- }
+ inner_iterations_are_enabled =
+ (inner_iteration_relative_progress >
+ options.inner_iteration_tolerance);
+ VLOG_IF(2, is_not_silent && !inner_iterations_are_enabled)
+ << "Disabling inner iterations. Progress : "
+ << inner_iteration_relative_progress;
}
summary->inner_iteration_time_in_seconds +=
WallTimeInSeconds() - inner_iteration_start_time;
@@ -356,12 +376,14 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
const double step_size_tolerance = options_.parameter_tolerance *
(x_norm + options_.parameter_tolerance);
if (iteration_summary.step_norm <= step_size_tolerance) {
- VLOG(1) << "Terminating. Parameter tolerance reached. "
- << "relative step_norm: "
- << iteration_summary.step_norm /
- (x_norm + options_.parameter_tolerance)
- << " <= " << options_.parameter_tolerance;
+ summary->error =
+ StringPrintf("Terminating. Parameter tolerance reached. "
+ "relative step_norm: %e <= %e.",
+ (iteration_summary.step_norm /
+ (x_norm + options_.parameter_tolerance)),
+ options_.parameter_tolerance);
summary->termination_type = PARAMETER_TOLERANCE;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
@@ -369,11 +391,13 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
const double absolute_function_tolerance =
options_.function_tolerance * cost;
if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
- VLOG(1) << "Terminating. Function tolerance reached. "
- << "|cost_change|/cost: "
- << fabs(iteration_summary.cost_change) / cost
- << " <= " << options_.function_tolerance;
+ summary->error =
+ StringPrintf("Terminating. Function tolerance reached. "
+ "|cost_change|/cost: %e <= %e",
+ fabs(iteration_summary.cost_change) / cost,
+ options_.function_tolerance);
summary->termination_type = FUNCTION_TOLERANCE;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
@@ -447,10 +471,12 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
if (!inner_iterations_were_useful &&
relative_decrease <= options_.min_relative_decrease) {
iteration_summary.step_is_nonmonotonic = true;
- VLOG(2) << "Non-monotonic step! "
- << " relative_decrease: " << relative_decrease
- << " historical_relative_decrease: "
- << historical_relative_decrease;
+ VLOG_IF(2, is_not_silent)
+ << "Non-monotonic step! "
+ << " relative_decrease: "
+ << relative_decrease
+ << " historical_relative_decrease: "
+ << historical_relative_decrease;
}
}
}
@@ -468,22 +494,25 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
residuals.data(),
gradient.data(),
jacobian)) {
- summary->termination_type = NUMERICAL_FAILURE;
summary->error =
"Terminating: Residual and Jacobian evaluation failed.";
- LOG(WARNING) << summary->error;
+ summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->error;
return;
}
iteration_summary.gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
+ iteration_summary.gradient_norm = gradient.norm();
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->error =
+ StringPrintf("Terminating: Gradient tolerance reached. "
+ "Relative gradient max norm: %e <= %e",
+ (iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm),
+ options_.gradient_tolerance);
summary->termination_type = GRADIENT_TOLERANCE;
- VLOG(1) << "Terminating: Gradient tolerance reached."
- << "Relative gradient max norm: "
- << (iteration_summary.gradient_max_norm /
- initial_gradient_max_norm)
- << " <= " << options_.gradient_tolerance;
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
@@ -511,7 +540,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
if (cost > candidate_cost) {
// The current iterate is has a higher cost than the
// candidate iterate. Set the candidate to this point.
- VLOG(2) << "Updating the candidate iterate to the current point.";
+ VLOG_IF(2, is_not_silent)
+ << "Updating the candidate iterate to the current point.";
candidate_cost = cost;
accumulated_candidate_model_cost_change = 0.0;
}
@@ -525,7 +555,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// iterate.
if (num_consecutive_nonmonotonic_steps ==
options.max_consecutive_nonmonotonic_steps) {
- VLOG(2) << "Resetting the reference point to the candidate point";
+ VLOG_IF(2, is_not_silent)
+ << "Resetting the reference point to the candidate point";
reference_cost = candidate_cost;
accumulated_reference_model_cost_change =
accumulated_candidate_model_cost_change;
@@ -544,8 +575,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.trust_region_radius = strategy->Radius();
if (iteration_summary.trust_region_radius <
options_.min_trust_region_radius) {
+ summary->error = "Termination. Minimum trust region radius reached.";
summary->termination_type = PARAMETER_TOLERANCE;
- VLOG(1) << "Termination. Minimum trust region radius reached.";
+ VLOG_IF(1, is_not_silent) << summary->error;
return;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
index 0dcdbfef016..998514fbfa5 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
@@ -33,7 +33,7 @@
#include <string>
#include "ceres/internal/port.h"
-#include "ceres/types.h"
+#include "ceres/linear_solver.h"
namespace ceres {
namespace internal {
@@ -106,7 +106,7 @@ class TrustRegionStrategy {
Summary()
: residual_norm(0.0),
num_iterations(-1),
- termination_type(FAILURE) {
+ termination_type(LINEAR_SOLVER_FAILURE) {
}
// If the trust region problem is,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc
index a97f1a55e6b..5f3455fdd41 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/types.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc
@@ -278,6 +278,25 @@ bool StringToCovarianceAlgorithmType(
return false;
}
+const char* VisibilityClusteringTypeToString(
+ VisibilityClusteringType type) {
+ switch (type) {
+ CASESTR(CANONICAL_VIEWS);
+ CASESTR(SINGLE_LINKAGE);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToVisibilityClusteringType(
+ string value,
+ VisibilityClusteringType* type) {
+ UpperCase(&value);
+ STRENUM(CANONICAL_VIEWS);
+ STRENUM(SINGLE_LINKAGE);
+ return false;
+}
+
const char* SolverTerminationTypeToString(SolverTerminationType type) {
switch (type) {
CASESTR(NO_CONVERGENCE);
@@ -293,18 +312,6 @@ const char* SolverTerminationTypeToString(SolverTerminationType type) {
}
}
-const char* LinearSolverTerminationTypeToString(
- LinearSolverTerminationType type) {
- switch (type) {
- CASESTR(TOLERANCE);
- CASESTR(MAX_ITERATIONS);
- CASESTR(STAGNATION);
- CASESTR(FAILURE);
- default:
- return "UNKNOWN";
- }
-}
-
#undef CASESTR
#undef STRENUM
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
index 7af133905b3..a3bebed2c1d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
@@ -43,12 +43,12 @@
#include "ceres/block_sparse_matrix.h"
#include "ceres/canonical_views_clustering.h"
#include "ceres/collections_port.h"
-#include "ceres/detect_structure.h"
#include "ceres/graph.h"
#include "ceres/graph_algorithms.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/schur_eliminator.h"
+#include "ceres/single_linkage_clustering.h"
#include "ceres/visibility.h"
#include "glog/logging.h"
@@ -61,8 +61,9 @@ namespace internal {
//
// This will require some more work on the clustering algorithm and
// possibly some more refactoring of the code.
-static const double kSizePenaltyWeight = 3.0;
-static const double kSimilarityPenaltyWeight = 0.0;
+static const double kCanonicalViewsSizePenaltyWeight = 3.0;
+static const double kCanonicalViewsSimilarityPenaltyWeight = 0.0;
+static const double kSingleLinkageMinSimilarity = 0.9;
VisibilityBasedPreconditioner::VisibilityBasedPreconditioner(
const CompressedRowBlockStructure& bs,
@@ -188,17 +189,31 @@ void VisibilityBasedPreconditioner::ClusterCameras(
scoped_ptr<Graph<int> > schur_complement_graph(
CHECK_NOTNULL(CreateSchurComplementGraph(visibility)));
- CanonicalViewsClusteringOptions options;
- options.size_penalty_weight = kSizePenaltyWeight;
- options.similarity_penalty_weight = kSimilarityPenaltyWeight;
-
- vector<int> centers;
HashMap<int, int> membership;
- ComputeCanonicalViewsClustering(*schur_complement_graph,
- options,
- &centers,
- &membership);
- num_clusters_ = centers.size();
+
+ if (options_.visibility_clustering_type == CANONICAL_VIEWS) {
+ vector<int> centers;
+ CanonicalViewsClusteringOptions clustering_options;
+ clustering_options.size_penalty_weight =
+ kCanonicalViewsSizePenaltyWeight;
+ clustering_options.similarity_penalty_weight =
+ kCanonicalViewsSimilarityPenaltyWeight;
+ ComputeCanonicalViewsClustering(clustering_options,
+ *schur_complement_graph,
+ &centers,
+ &membership);
+ num_clusters_ = centers.size();
+ } else if (options_.visibility_clustering_type == SINGLE_LINKAGE) {
+ SingleLinkageClusteringOptions clustering_options;
+ clustering_options.min_similarity =
+ kSingleLinkageMinSimilarity;
+ num_clusters_ = ComputeSingleLinkageClustering(clustering_options,
+ *schur_complement_graph,
+ &membership);
+ } else {
+ LOG(FATAL) << "Unknown visibility clustering algorithm.";
+ }
+
CHECK_GT(num_clusters_, 0);
VLOG(2) << "num_clusters: " << num_clusters_;
FlattenMembershipMap(membership, &cluster_membership_);
@@ -313,14 +328,11 @@ void VisibilityBasedPreconditioner::InitEliminator(
LinearSolver::Options eliminator_options;
eliminator_options.elimination_groups = options_.elimination_groups;
eliminator_options.num_threads = options_.num_threads;
-
- DetectStructure(bs, options_.elimination_groups[0],
- &eliminator_options.row_block_size,
- &eliminator_options.e_block_size,
- &eliminator_options.f_block_size);
-
+ eliminator_options.e_block_size = options_.e_block_size;
+ eliminator_options.f_block_size = options_.f_block_size;
+ eliminator_options.row_block_size = options_.row_block_size;
eliminator_.reset(SchurEliminatorBase::Create(eliminator_options));
- eliminator_->Init(options_.elimination_groups[0], &bs);
+ eliminator_->Init(eliminator_options.elimination_groups[0], &bs);
}
// Update the values of the preconditioner matrix and factorize it.
@@ -356,14 +368,18 @@ bool VisibilityBasedPreconditioner::UpdateImpl(const BlockSparseMatrix& A,
//
// Doing the factorization like this saves us matrix mass when
// scaling is not needed, which is quite often in our experience.
- bool status = Factorize();
+ LinearSolverTerminationType status = Factorize();
+
+ if (status == LINEAR_SOLVER_FATAL_ERROR) {
+ return false;
+ }
// The scaling only affects the tri-diagonal case, since
// ScaleOffDiagonalBlocks only pays attenion to the cells that
// belong to the edges of the degree-2 forest. In the CLUSTER_JACOBI
// case, the preconditioner is guaranteed to be positive
// semidefinite.
- if (!status && options_.type == CLUSTER_TRIDIAGONAL) {
+ if (status == LINEAR_SOLVER_FAILURE && options_.type == CLUSTER_TRIDIAGONAL) {
VLOG(1) << "Unscaled factorization failed. Retrying with off-diagonal "
<< "scaling";
ScaleOffDiagonalCells();
@@ -371,7 +387,7 @@ bool VisibilityBasedPreconditioner::UpdateImpl(const BlockSparseMatrix& A,
}
VLOG(2) << "Compute time: " << time(NULL) - start_time;
- return status;
+ return (status == LINEAR_SOLVER_SUCCESS);
}
// Consider the preconditioner matrix as meta-block matrix, whose
@@ -408,7 +424,7 @@ void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() {
// Compute the sparse Cholesky factorization of the preconditioner
// matrix.
-bool VisibilityBasedPreconditioner::Factorize() {
+LinearSolverTerminationType VisibilityBasedPreconditioner::Factorize() {
// Extract the TripletSparseMatrix that is used for actually storing
// S and convert it into a cholmod_sparse object.
cholmod_sparse* lhs = ss_.CreateSparseMatrix(
@@ -419,14 +435,21 @@ bool VisibilityBasedPreconditioner::Factorize() {
// matrix contains the values.
lhs->stype = 1;
+ // TODO(sameeragarwal): Refactor to pipe this up and out.
+ string status;
+
// Symbolic factorization is computed if we don't already have one handy.
if (factor_ == NULL) {
- factor_ = ss_.BlockAnalyzeCholesky(lhs, block_size_, block_size_);
+ factor_ = ss_.BlockAnalyzeCholesky(lhs, block_size_, block_size_, &status);
}
- bool status = ss_.Cholesky(lhs, factor_);
+ const LinearSolverTerminationType termination_type =
+ (factor_ != NULL)
+ ? ss_.Cholesky(lhs, factor_, &status)
+ : LINEAR_SOLVER_FATAL_ERROR;
+
ss_.Free(lhs);
- return status;
+ return termination_type;
}
void VisibilityBasedPreconditioner::RightMultiply(const double* x,
@@ -437,7 +460,10 @@ void VisibilityBasedPreconditioner::RightMultiply(const double* x,
const int num_rows = m_->num_rows();
memcpy(CHECK_NOTNULL(tmp_rhs_)->x, x, m_->num_rows() * sizeof(*x));
- cholmod_dense* solution = CHECK_NOTNULL(ss->Solve(factor_, tmp_rhs_));
+ // TODO(sameeragarwal): Better error handling.
+ string status;
+ cholmod_dense* solution =
+ CHECK_NOTNULL(ss->Solve(factor_, tmp_rhs_, &status));
memcpy(y, solution->x, sizeof(*y) * num_rows);
ss->Free(solution);
}
@@ -546,11 +572,17 @@ Graph<int>* VisibilityBasedPreconditioner::CreateClusterGraph(
// cluster ids. Convert this into a flat array for quick lookup. It is
// possible that some of the vertices may not be associated with any
// cluster. In that case, randomly assign them to one of the clusters.
+//
+// The cluster ids can be non-contiguous integers. So as we flatten
+// the membership_map, we also map the cluster ids to a contiguous set
+// of integers so that the cluster ids are in [0, num_clusters_).
void VisibilityBasedPreconditioner::FlattenMembershipMap(
const HashMap<int, int>& membership_map,
vector<int>* membership_vector) const {
CHECK_NOTNULL(membership_vector)->resize(0);
membership_vector->resize(num_blocks_, -1);
+
+ HashMap<int, int> cluster_id_to_index;
// Iterate over the cluster membership map and update the
// cluster_membership_ vector assigning arbitrary cluster ids to
// the few cameras that have not been clustered.
@@ -571,7 +603,16 @@ void VisibilityBasedPreconditioner::FlattenMembershipMap(
cluster_id = camera_id % num_clusters_;
}
- membership_vector->at(camera_id) = cluster_id;
+ const int index = FindWithDefault(cluster_id_to_index,
+ cluster_id,
+ cluster_id_to_index.size());
+
+ if (index == cluster_id_to_index.size()) {
+ cluster_id_to_index[cluster_id] = index;
+ }
+
+ CHECK_LT(index, num_clusters_);
+ membership_vector->at(camera_id) = index;
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
index c58b1a7a90a..70cea83bf56 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
@@ -55,6 +55,7 @@
#include "ceres/graph.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_solver.h"
#include "ceres/preconditioner.h"
#include "ceres/suitesparse.h"
@@ -147,7 +148,7 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner {
void ComputeClusterTridiagonalSparsity(const CompressedRowBlockStructure& bs);
void InitStorage(const CompressedRowBlockStructure& bs);
void InitEliminator(const CompressedRowBlockStructure& bs);
- bool Factorize();
+ LinearSolverTerminationType Factorize();
void ScaleOffDiagonalCells();
void ClusterCameras(const vector< set<int> >& visibility);
diff --git a/extern/libmv/third_party/glog/src/logging.cc b/extern/libmv/third_party/glog/src/logging.cc
index f36e14d2ce4..57d5e24122c 100644
--- a/extern/libmv/third_party/glog/src/logging.cc
+++ b/extern/libmv/third_party/glog/src/logging.cc
@@ -34,6 +34,7 @@
#include <assert.h>
#include <iomanip>
#include <string>
+#include <algorithm>
#ifdef HAVE_UNISTD_H
# include <unistd.h> // For _exit.
#endif
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index c45e66cd77b..b7aff03a710 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -29,7 +29,6 @@ add_subdirectory(ghost)
add_subdirectory(guardedalloc)
add_subdirectory(memutil)
add_subdirectory(opencolorio)
-add_subdirectory(opennl)
add_subdirectory(mikktspace)
add_subdirectory(raskter)
@@ -81,6 +80,10 @@ if(WITH_COMPOSITOR)
add_subdirectory(opencl)
endif()
+if(WITH_OPENNL)
+ add_subdirectory(opennl)
+endif()
+
# only windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.cpp b/intern/audaspace/intern/AUD_JOSResampleReader.cpp
index 87577da95cc..0448c75d777 100644
--- a/intern/audaspace/intern/AUD_JOSResampleReader.cpp
+++ b/intern/audaspace/intern/AUD_JOSResampleReader.cpp
@@ -36,6 +36,7 @@
/* MSVC does not have lrint */
#ifdef _MSC_VER
+#if _MSC_VER < 1800
#ifdef _M_X64
#include <emmintrin.h>
static inline int lrint(double d)
@@ -56,6 +57,7 @@ static inline int lrint(double d)
}
#endif
#endif
+#endif
// UNUSED
// #define CC m_channels + channel
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 6821e93ad87..fc193d99a57 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -17,9 +17,11 @@ if(WIN32 AND MSVC)
if(CMAKE_CL_64)
set(CYCLES_SSE2_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
set(CYCLES_SSE3_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
else()
set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /Gs-")
@@ -29,10 +31,12 @@ if(WIN32 AND MSVC)
elseif(CMAKE_COMPILER_IS_GNUCC)
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")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
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")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
endif()
@@ -58,6 +62,14 @@ if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
+if(WITH_CYCLES_PTEX)
+ add_definitions(-DWITH_PTEX)
+endif()
+
+if(WITH_CYCLES_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
if(WITH_CYCLES_OSL)
add_definitions(-DWITH_OSL)
add_definitions(-DOSL_STATIC_LIBRARY)
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index e61018bc3dd..eeb60f37f92 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -37,6 +37,7 @@ sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('
sources.remove(path.join('util', 'util_view.cpp'))
sources.remove(path.join('kernel', 'kernel_sse2.cpp'))
sources.remove(path.join('kernel', 'kernel_sse3.cpp'))
+sources.remove(path.join('kernel', 'kernel_sse41.cpp'))
incs = []
defs = []
@@ -77,21 +78,30 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
if env['WITH_BF_RAYOPTIMIZATION']:
sse2_cxxflags = Split(env['CXXFLAGS'])
sse3_cxxflags = Split(env['CXXFLAGS'])
+ sse41_cxxflags = Split(env['CXXFLAGS'])
if env['OURPLATFORM'] == 'win32-vc':
# there is no /arch:SSE3, but intrinsics are available anyway
sse2_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
sse3_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
+ sse41_cxxflags.append('/arch:SSE /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
elif env['OURPLATFORM'] == 'win64-vc':
sse2_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
sse3_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
+ sse41_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /Ox /Gs-'.split())
else:
sse2_cxxflags.append('-ffast-math -msse -msse2 -mfpmath=sse'.split())
sse3_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse'.split())
+ sse41_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mfpmath=sse'.split())
defs.append('WITH_OPTIMIZED_KERNEL')
optim_defs = defs[:]
+ # Disabled sse4+ patchs for now
+ #cycles_sse41 = cycles.Clone()
+ #sse41_sources = [path.join('kernel', 'kernel_sse41.cpp')]
+ #cycles_sse41.BlenderLib('bf_intern_cycles_sse41', sse41_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse41_cxxflags)
+
cycles_sse3 = cycles.Clone()
sse3_sources = [path.join('kernel', 'kernel_sse3.cpp')]
cycles_sse3.BlenderLib('bf_intern_cycles_sse3', sse3_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse3_cxxflags)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index a2142d77a9e..8a81ddde1e1 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -30,6 +30,10 @@ set(LIBRARIES
${TIFF_LIBRARY}
)
+if(UNIX)
+ list(APPEND LIBRARIES dl)
+endif()
+
if(WIN32)
list(APPEND LIBRARIES ${PTHREADS_LIBRARIES})
endif()
@@ -41,7 +45,7 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
endif()
if(WITH_CYCLES_OSL)
- list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES})
+ list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES} ${LLVM_LIBRARY})
endif()
include_directories(${INC})
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index e80fc0cb95f..f4cacb2d001 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -35,6 +35,7 @@ int main(int argc, const char **argv)
string devicelist = "";
string devicename = "cpu";
bool list = false;
+ int threads = 0;
vector<DeviceType>& types = Device::available_types();
@@ -51,6 +52,7 @@ int main(int argc, const char **argv)
ap.options ("Usage: cycles_server [options]",
"--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",
NULL);
if(ap.parse(argc, argv) < 0) {
@@ -84,11 +86,11 @@ int main(int argc, const char **argv)
}
}
- TaskScheduler::init();
+ TaskScheduler::init(threads);
while(1) {
Stats stats;
- Device *device = Device::create(device_info, stats);
+ Device *device = Device::create(device_info, stats, true);
printf("Cycles Server with device: %s\n", device->info.description.c_str());
device->server_run();
delete device;
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 55a2a30b9a8..df187f046e5 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -703,15 +703,14 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
}
/* finalize subd mesh */
- sdmesh.link_boundary();
-
- /* subdivide */
- DiagSplit dsplit;
- //dsplit.camera = state.scene->camera;
- //dsplit.dicing_rate = 5.0f;
- dsplit.dicing_rate = state.dicing_rate;
- xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
- sdmesh.tessellate(&dsplit, false, mesh, shader, smooth);
+ sdmesh.finish();
+
+ /* parameters */
+ SubdParams sdparams(mesh, shader, smooth);
+ xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
+
+ DiagSplit dsplit(sdparams);;
+ sdmesh.tessellate(&dsplit);
}
else {
/* create vertices */
@@ -789,12 +788,11 @@ static void xml_read_patch(const XMLReadState& state, pugi::xml_node node)
mesh->used_shaders.push_back(state.shader);
/* split */
- DiagSplit dsplit;
- //dsplit.camera = state.scene->camera;
- //dsplit.dicing_rate = 5.0f;
- dsplit.dicing_rate = state.dicing_rate;
- xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
- dsplit.split_quad(mesh, patch, state.shader, state.smooth);
+ SubdParams sdparams(mesh, state.shader, state.smooth);
+ xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
+
+ DiagSplit dsplit(sdparams);
+ dsplit.split_quad(patch);
delete patch;
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index 29d8ed0d98e..6532315cf39 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -30,7 +30,7 @@ typedef struct CCLDeviceInfo {
int value;
} CCLDeviceInfo;
-CCLDeviceInfo *CCL_compute_device_list(int opencl);
+CCLDeviceInfo *CCL_compute_device_list(int device_type);
/* create python module _cycles used by addon */
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 3f15e232de7..66dc5e78e5a 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -88,3 +88,7 @@ def available_devices():
def with_osl():
import _cycles
return _cycles.with_osl
+
+def with_network():
+ import _cycles
+ return _cycles.with_network
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index ac15acee0c5..f5c052e7f0c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -25,9 +25,15 @@ from bpy.props import (BoolProperty,
# enums
+import _cycles
+
enum_devices = (
- ('CPU', "CPU", "Use CPU for rendering"),
- ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
+ ('CPU', "CPU", "Use CPU for rendering"),
+ ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"),
+ )
+
+if _cycles.with_network:
+ enum_devices += (('NETWORK', "Networked Device", "Use networked device for rendering"),)
enum_feature_set = (
('SUPPORTED', "Supported", "Only use finished and supported features"),
@@ -621,6 +627,7 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup):
@classmethod
def unregister(cls):
del bpy.types.Object.cycles_visibility
+ del bpy.types.World.cycles_visibility
class CyclesMeshSettings(bpy.types.PropertyGroup):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index cbf26fb8d0a..05d3c15d076 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -311,31 +311,6 @@ class CyclesRender_PT_opengl(CyclesButtonsPanel, Panel):
col.prop(rd, "alpha_mode", text="")
-class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
- bl_label = "Layer List"
- bl_context = "render_layer"
- bl_options = {'HIDE_HEADER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- rl = rd.layers.active
-
- row = layout.row()
- row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=1)
-
- col = row.column(align=True)
- col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
- col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- if rl:
- row.prop(rl, "name")
- row.prop(rd, "use_single_layer", text="", icon_only=True)
-
-
class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
bl_label = "Layer"
bl_context = "render_layer"
@@ -1275,9 +1250,7 @@ def draw_device(self, context):
layout.prop(cscene, "feature_set")
device_type = context.user_preferences.system.compute_device_type
- if device_type == 'CUDA':
- layout.prop(cscene, "device")
- elif device_type == 'OPENCL':
+ if device_type in {'CUDA', 'OPENCL', 'NETWORK'}:
layout.prop(cscene, "device")
if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'):
@@ -1306,6 +1279,7 @@ def get_panels():
types.RENDER_PT_encoding,
types.RENDER_PT_dimensions,
types.RENDER_PT_stamp,
+ types.RENDERLAYER_PT_layers,
types.SCENE_PT_scene,
types.SCENE_PT_color_management,
types.SCENE_PT_custom_props,
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index b780877a158..da4acf16a4d 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -400,6 +400,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
float3 xbasis;
float3 v1;
@@ -460,6 +462,8 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
if(len_squared(firstxbasis)!= 0.0f)
@@ -593,7 +597,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
- if(CData->curve_keynum[curve] <= 1)
+ if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
continue;
size_t num_curve_keys = 0;
@@ -644,7 +648,7 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat
continue;
for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- if(CData->curve_keynum[curve] <= 1)
+ if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
continue;
for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
@@ -683,6 +687,8 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
@@ -724,6 +730,8 @@ void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offs
for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+ if(CData->curve_length[curve] == 0.0f)
+ continue;
for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index e42af60c27b..0e46903a50c 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -365,7 +365,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
}
}
-static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
+static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
/* create subd mesh */
SubdMesh sdmesh;
@@ -386,21 +386,25 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
if(n == 4)
sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
-#if 0
else
sdmesh.add_face(vi[0], vi[1], vi[2]);
-#endif
}
/* finalize subd mesh */
- sdmesh.link_boundary();
+ sdmesh.finish();
- /* subdivide */
- DiagSplit dsplit;
- dsplit.camera = NULL;
- dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
+ /* parameters */
+ bool need_ptex = mesh->need_attribute(scene, ATTR_STD_PTEX_FACE_ID) ||
+ mesh->need_attribute(scene, ATTR_STD_PTEX_UV);
- sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
+ SubdParams sdparams(mesh, used_shaders[0], true, need_ptex);
+ sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
+ //scene->camera->update();
+ //sdparams.camera = scene->camera;
+
+ /* tesselate */
+ DiagSplit dsplit(sdparams);;
+ sdmesh.tessellate(&dsplit);
}
/* Sync */
@@ -482,7 +486,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
if(b_mesh) {
if(render_layer.use_surfaces && !hide_tris) {
if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
- create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
+ create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders);
else
create_mesh(scene, mesh, b_mesh, used_shaders);
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index ba584e172dc..0df8939bc18 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -267,13 +267,38 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
/* mesh sync */
object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
- /* sspecial case not tracked by object update flags */
+ /* special case not tracked by object update flags */
+
+ /* holdout */
if(use_holdout != object->use_holdout) {
object->use_holdout = use_holdout;
scene->object_manager->tag_update(scene);
object_updated = true;
}
+ /* visibility flags for both parent and child */
+ uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
+ if(b_parent.ptr.data != b_ob.ptr.data) {
+ visibility &= object_ray_visibility(b_parent);
+ object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
+ }
+
+ /* make holdout objects on excluded layer invisible for non-camera rays */
+ if(use_holdout && (layer_flag & render_layer.exclude_layer))
+ visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
+
+ /* camera flag is not actually used, instead is tested against render layer
+ * flags */
+ if(visibility & PATH_RAY_CAMERA) {
+ visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
+ visibility &= ~PATH_RAY_CAMERA;
+ }
+
+ if(visibility != object->visibility) {
+ object->visibility = visibility;
+ object_updated = true;
+ }
+
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
@@ -295,24 +320,10 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
else
object->random_id = hash_int_2d(object->random_id, 0);
- /* visibility flags for both parent */
- object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
- if(b_parent.ptr.data != b_ob.ptr.data) {
- object->visibility &= object_ray_visibility(b_parent);
+ if(b_parent.ptr.data != b_ob.ptr.data)
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
- }
-
- /* make holdout objects on excluded layer invisible for non-camera rays */
- if(use_holdout && (layer_flag & render_layer.exclude_layer))
- object->visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
-
- /* camera flag is not actually used, instead is tested
- * against render layer flags */
- if(object->visibility & PATH_RAY_CAMERA) {
- object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
- object->visibility &= ~PATH_RAY_CAMERA;
- }
+ /* dupli texture coordinates */
if (b_dupli_ob) {
object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
object->dupli_uv = get_float2(b_dupli_ob.uv());
@@ -346,6 +357,7 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
bool hair_present = false;
bool show_emitter = false;
+ bool hide_emitter = false;
bool hide_as_dupli_parent = false;
bool hide_as_dupli_child_original = false;
@@ -356,8 +368,13 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
if(b_psys->settings().use_render_emitter())
show_emitter = true;
+ else
+ hide_emitter = true;
}
+ if(show_emitter)
+ hide_emitter = false;
+
/* duplicators hidden by default, except dupliframes which duplicate self */
if(b_ob.is_duplicator())
if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
@@ -369,16 +386,15 @@ static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide
if(parent_hide)
hide_as_dupli_child_original = true;
+ hide_triangles = hide_emitter;
+
if(show_emitter) {
- hide_triangles = false;
return false;
}
else if(hair_present) {
- hide_triangles = true;
return hide_as_dupli_child_original;
}
else {
- hide_triangles = false;
return (hide_as_dupli_parent || hide_as_dupli_child_original);
}
}
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 71c84869ff6..22c425aa332 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -475,19 +475,55 @@ void *CCL_python_module_init()
PyObject *mod = PyModule_Create(&ccl::module);
#ifdef WITH_OSL
+ /* TODO(sergey): This gives us library we've been linking against.
+ * In theory with dynamic OSL library it might not be
+ * accurate, but there's nothing in OSL API which we
+ * might use th get version in runtime.
+ */
+ int curversion = OSL_LIBRARY_VERSION_CODE;
PyModule_AddObject(mod, "with_osl", Py_True);
Py_INCREF(Py_True);
+ PyModule_AddObject(mod, "osl_version",
+ Py_BuildValue("(iii)",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ PyModule_AddObject(mod, "osl_version_string",
+ PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
PyModule_AddObject(mod, "with_osl", Py_False);
Py_INCREF(Py_False);
+ PyModule_AddStringConstant(mod, "osl_version", "unknown");
+ PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
+#ifdef WITH_NETWORK
+ PyModule_AddObject(mod, "with_network", Py_True);
+ Py_INCREF(Py_True);
+#else /* WITH_NETWORK */
+ PyModule_AddObject(mod, "with_network", Py_False);
+ Py_INCREF(Py_False);
+#endif /* WITH_NETWORK */
+
return (void*)mod;
}
-CCLDeviceInfo *CCL_compute_device_list(int opencl)
+CCLDeviceInfo *CCL_compute_device_list(int device_type)
{
- ccl::DeviceType type = (opencl)? ccl::DEVICE_OPENCL: ccl::DEVICE_CUDA;
+ ccl::DeviceType type;
+ switch(device_type) {
+ case 0:
+ type = ccl::DEVICE_CUDA;
+ break;
+ case 1:
+ type = ccl::DEVICE_OPENCL;
+ break;
+ case 2:
+ type = ccl::DEVICE_NETWORK;
+ break;
+ default:
+ type = ccl::DEVICE_NONE;
+ break;
+ }
return ccl::compute_device_list(type);
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 84ff071171b..db673a8d625 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -625,28 +625,42 @@ void BlenderSession::get_progress(float& progress, double& total_time)
void BlenderSession::update_status_progress()
{
string timestatus, status, substatus;
+ string scene = "";
float progress;
- double total_time;
+ double total_time, remaining_time = 0;
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);
- timestatus = string_printf("Mem:%.2fM, Peak:%.2fM", mem_used, mem_peak);
+
if(background) {
- timestatus += " | " + b_scene.name();
+ if(progress>0)
+ remaining_time = (1-progress) * (total_time / progress);
+
+ scene += " | " + b_scene.name();
if(b_rlay_name != "")
- timestatus += ", " + b_rlay_name;
+ scene += ", " + b_rlay_name;
}
else {
- timestatus += " | ";
-
BLI_timestr(total_time, time_str, sizeof(time_str));
- timestatus += "Time:" + string(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) {
+ BLI_timestr(remaining_time, time_str, sizeof(time_str));
+ timestatus += "Remaining:" + string(time_str) + " | ";
+ }
+
+ timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", mem_used, mem_peak);
if(status.size() > 0)
status = " | " + status;
@@ -654,12 +668,12 @@ void BlenderSession::update_status_progress()
status += " | " + substatus;
if(status != last_status) {
- b_engine.update_stats("", (timestatus + status).c_str());
b_engine.update_memory_stats(mem_used, mem_peak);
last_status = status;
}
if(progress != last_progress) {
b_engine.update_progress(progress);
+ b_engine.update_stats("", (timestatus + scene + status).c_str());
last_progress = progress;
}
}
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index fe2368b7ea8..825e82209aa 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -13,6 +13,10 @@ set(INC_SYS
${GLEW_INCLUDE_PATH}
)
+if(WITH_CYCLES_OPTIMIZED_KERNEL_SSE41)
+ add_definitions(-DWITH_CYCLES_OPTIMIZED_KERNEL_SSE41=1)
+endif()
+
set(SRC
device.cpp
device_cpu.cpp
@@ -22,7 +26,7 @@ set(SRC
device_task.cpp
)
-if(WITH_NETWORK)
+if(WITH_CYCLES_NETWORK)
list(APPEND SRC
device_network.cpp
)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 5c771aa1c8b..6283e34f563 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -127,7 +127,7 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
switch(info.type) {
case DEVICE_CPU:
- device = device_cpu_create(info, stats);
+ device = device_cpu_create(info, stats, background);
break;
#ifdef WITH_CUDA
case DEVICE_CUDA:
@@ -159,9 +159,6 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
return NULL;
}
- if(device)
- device->info = info;
-
return device;
}
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 18868d19a85..bd309e35788 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -71,7 +71,7 @@ public:
class Device {
protected:
- Device(Stats &stats_) : stats(stats_) {}
+ Device(DeviceInfo& info_, Stats &stats_, bool background) : background(background), info(info_), stats(stats_) {}
bool background;
string error_msg;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index d04c5df82fb..e084116c72d 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -45,11 +45,13 @@ class CPUDevice : public Device
public:
TaskPool task_pool;
KernelGlobals kernel_globals;
+
#ifdef WITH_OSL
OSLGlobals osl_globals;
#endif
- CPUDevice(Stats &stats) : Device(stats)
+ CPUDevice(DeviceInfo& info, Stats &stats, bool background)
+ : Device(info, stats, background)
{
#ifdef WITH_OSL
kernel_globals.osl = &osl_globals;
@@ -58,6 +60,7 @@ public:
/* do now to avoid thread issues */
system_cpu_support_sse2();
system_cpu_support_sse3();
+ system_cpu_support_sse41();
}
~CPUDevice()
@@ -164,6 +167,28 @@ public:
int end_sample = tile.start_sample + tile.num_samples;
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int sample = start_sample; sample < end_sample; sample++) {
+ if (task.get_cancel() || task_pool.canceled()) {
+ if(task.need_finish_queue == false)
+ break;
+ }
+
+ for(int y = tile.y; y < tile.y + tile.h; y++) {
+ for(int x = tile.x; x < tile.x + tile.w; x++) {
+ kernel_cpu_sse41_path_trace(&kg, render_buffer, rng_state,
+ sample, x, y, tile.offset, tile.stride);
+ }
+ }
+
+ tile.sample = sample + 1;
+
+ task.update_progress(tile);
+ }
+ }
+ else
+#endif
if(system_cpu_support_sse3()) {
for(int sample = start_sample; sample < end_sample; sample++) {
if (task.get_cancel() || task_pool.canceled()) {
@@ -243,6 +268,15 @@ public:
if(task.rgba_half) {
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ kernel_cpu_sse41_convert_to_half_float(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
+ }
+ else
+#endif
if(system_cpu_support_sse3()) {
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
@@ -266,6 +300,14 @@ public:
}
else {
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int y = task.y; y < task.y + task.h; y++)
+ for(int x = task.x; x < task.x + task.w; x++)
+ kernel_cpu_sse41_convert_to_byte(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
+ sample_scale, x, y, task.offset, task.stride);
+ }
+#endif
if(system_cpu_support_sse3()) {
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
@@ -298,6 +340,16 @@ public:
#endif
#ifdef WITH_OPTIMIZED_KERNEL
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
+ kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
+
+ if(task_pool.canceled())
+ break;
+ }
+ }
+#endif
if(system_cpu_support_sse3()) {
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
@@ -351,9 +403,9 @@ public:
}
};
-Device *device_cpu_create(DeviceInfo& info, Stats &stats)
+Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background)
{
- return new CPUDevice(stats);
+ return new CPUDevice(info, stats, background);
}
void device_cpu_info(vector<DeviceInfo>& devices)
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 4ce7f6fd729..8db915f769c 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -171,7 +171,8 @@ public:
cuda_assert(cuCtxSetCurrent(NULL));
}
- CUDADevice(DeviceInfo& info, Stats &stats, bool background_) : Device(stats)
+ CUDADevice(DeviceInfo& info, Stats &stats, bool background_)
+ : Device(info, stats, background_)
{
first_error = true;
background = background_;
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index d667478beed..7eb66c25a81 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
class Device;
-Device *device_cpu_create(DeviceInfo& info, Stats &stats);
+Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background);
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address);
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 4df0fdbd4c7..27b9de0769e 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -45,25 +45,24 @@ public:
device_ptr unique_ptr;
MultiDevice(DeviceInfo& info, Stats &stats, bool background_)
- : Device(stats), unique_ptr(1)
+ : Device(info, stats, background_), unique_ptr(1)
{
Device *device;
- background = background_;
foreach(DeviceInfo& subinfo, info.multi_devices) {
device = Device::create(subinfo, stats, background);
devices.push_back(SubDevice(device));
}
-#if 0 //def WITH_NETWORK
+#ifdef WITH_NETWORK
/* try to add network devices */
ServerDiscovery discovery(true);
time_sleep(1.0);
- list<string> servers = discovery.get_server_list();
+ vector<string> servers = discovery.get_server_list();
foreach(string& server, servers) {
- device = device_network_create(info, server.c_str());
+ device = device_network_create(info, stats, server.c_str());
if(device)
devices.push_back(SubDevice(device));
}
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index 23c1a10fa0a..90339b89cce 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -20,9 +20,25 @@
#include "util_foreach.h"
+#if defined(WITH_NETWORK)
+
CCL_NAMESPACE_BEGIN
-#ifdef WITH_NETWORK
+typedef map<device_ptr, device_ptr> PtrMap;
+typedef vector<uint8_t> DataVector;
+typedef map<device_ptr, DataVector> DataMap;
+
+/* tile list */
+typedef vector<RenderTile> TileList;
+
+/* search a list of tiles and find the one that matches the passed render tile */
+static TileList::iterator tile_list_find(TileList& tile_list, RenderTile& tile)
+{
+ for(TileList::iterator it = tile_list.begin(); it != tile_list.end(); ++it)
+ if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample)
+ return it;
+ return tile_list.end();
+}
class NetworkDevice : public Device
{
@@ -32,8 +48,10 @@ public:
device_ptr mem_counter;
DeviceTask the_task; /* todo: handle multiple tasks */
- NetworkDevice(Stats &stats, const char *address)
- : Device(stats), socket(io_service)
+ thread_mutex rpc_lock;
+
+ NetworkDevice(DeviceInfo& info, Stats &stats, const char *address)
+ : Device(info, stats, true), socket(io_service)
{
stringstream portstr;
portstr << SERVER_PORT;
@@ -64,6 +82,8 @@ public:
void mem_alloc(device_memory& mem, MemoryType type)
{
+ thread_scoped_lock lock(rpc_lock);
+
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "mem_alloc");
@@ -75,6 +95,8 @@ public:
void mem_copy_to(device_memory& mem)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_copy_to");
snd.add(mem);
@@ -84,6 +106,10 @@ public:
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
{
+ thread_scoped_lock lock(rpc_lock);
+
+ size_t data_size = mem.memory_size();
+
RPCSend snd(socket, "mem_copy_from");
snd.add(mem);
@@ -94,11 +120,13 @@ public:
snd.write();
RPCReceive rcv(socket);
- rcv.read_buffer((void*)mem.data_pointer, mem.memory_size());
+ rcv.read_buffer((void*)mem.data_pointer, data_size);
}
void mem_zero(device_memory& mem)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_zero");
snd.add(mem);
@@ -108,6 +136,8 @@ public:
void mem_free(device_memory& mem)
{
if(mem.device_pointer) {
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "mem_free");
snd.add(mem);
@@ -119,6 +149,8 @@ public:
void const_copy_to(const char *name, void *host, size_t size)
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "const_copy_to");
string name_string(name);
@@ -131,6 +163,8 @@ public:
void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic)
{
+ thread_scoped_lock lock(rpc_lock);
+
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "tex_alloc");
@@ -148,6 +182,8 @@ public:
void tex_free(device_memory& mem)
{
if(mem.device_pointer) {
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "tex_free");
snd.add(mem);
@@ -157,8 +193,25 @@ public:
}
}
+ bool load_kernels(bool experimental)
+ {
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, "load_kernels");
+ snd.add(experimental);
+ snd.write();
+
+ bool result;
+ RPCReceive rcv(socket);
+ rcv.read(result);
+
+ return result;
+ }
+
void task_add(DeviceTask& task)
{
+ thread_scoped_lock lock(rpc_lock);
+
the_task = task;
RPCSend snd(socket, "task_add");
@@ -168,55 +221,73 @@ public:
void task_wait()
{
+ thread_scoped_lock lock(rpc_lock);
+
RPCSend snd(socket, "task_wait");
snd.write();
- list<RenderTile> the_tiles;
+ lock.unlock();
+
+ TileList the_tiles;
/* todo: run this threaded for connecting to multiple clients */
for(;;) {
- RPCReceive rcv(socket);
RenderTile tile;
+ lock.lock();
+ RPCReceive rcv(socket);
+
if(rcv.name == "acquire_tile") {
+ lock.unlock();
+
/* todo: watch out for recursive calls! */
if(the_task.acquire_tile(this, tile)) { /* write return as bool */
the_tiles.push_back(tile);
+ lock.lock();
RPCSend snd(socket, "acquire_tile");
snd.add(tile);
snd.write();
+ lock.unlock();
}
else {
+ lock.lock();
RPCSend snd(socket, "acquire_tile_none");
snd.write();
+ lock.unlock();
}
}
else if(rcv.name == "release_tile") {
rcv.read(tile);
+ lock.unlock();
- for(list<RenderTile>::iterator it = the_tiles.begin(); it != the_tiles.end(); it++) {
- if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample) {
- tile.buffers = it->buffers;
- the_tiles.erase(it);
- break;
- }
+ TileList::iterator it = tile_list_find(the_tiles, tile);
+ if (it != the_tiles.end()) {
+ tile.buffers = it->buffers;
+ the_tiles.erase(it);
}
assert(tile.buffers != NULL);
the_task.release_tile(tile);
+ lock.lock();
RPCSend snd(socket, "release_tile");
snd.write();
+ lock.unlock();
}
- else if(rcv.name == "task_wait_done")
+ else if(rcv.name == "task_wait_done") {
+ lock.unlock();
break;
+ }
+ else
+ lock.unlock();
}
}
void task_cancel()
{
+ thread_scoped_lock lock(rpc_lock);
RPCSend snd(socket, "task_cancel");
snd.write();
}
@@ -224,7 +295,7 @@ public:
Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address)
{
- return new NetworkDevice(stats, address);
+ return new NetworkDevice(info, stats, address);
}
void device_network_info(vector<DeviceInfo>& devices)
@@ -243,8 +314,10 @@ void device_network_info(vector<DeviceInfo>& devices)
class DeviceServer {
public:
+ thread_mutex rpc_lock;
+
DeviceServer(Device *device_, tcp::socket& socket_)
- : device(device_), socket(socket_)
+ : device(device_), socket(socket_), stop(false), blocked_waiting(false)
{
}
@@ -252,56 +325,151 @@ public:
{
/* receive remote function calls */
for(;;) {
- RPCReceive rcv(socket);
+ listen_step();
- if(rcv.name == "stop")
+ if(stop)
break;
-
- process(rcv);
}
}
protected:
- void process(RPCReceive& rcv)
+ void listen_step()
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCReceive rcv(socket);
+
+ if(rcv.name == "stop")
+ stop = true;
+ else
+ process(rcv, lock);
+ }
+
+ /* create a memory buffer for a device buffer and insert it into mem_data */
+ DataVector &data_vector_insert(device_ptr client_pointer, size_t data_size)
+ {
+ /* create a new DataVector and insert it into mem_data */
+ pair<DataMap::iterator,bool> data_ins = mem_data.insert(
+ DataMap::value_type(client_pointer, DataVector()));
+
+ /* make sure it was a unique insertion */
+ assert(data_ins.second);
+
+ /* get a reference to the inserted vector */
+ DataVector &data_v = data_ins.first->second;
+
+ /* size the vector */
+ data_v.resize(data_size);
+
+ return data_v;
+ }
+
+ DataVector &data_vector_find(device_ptr client_pointer)
{
- // fprintf(stderr, "receive process %s\n", rcv.name.c_str());
+ DataMap::iterator i = mem_data.find(client_pointer);
+ assert(i != mem_data.end());
+ return i->second;
+ }
+
+ /* setup mapping and reverse mapping of client_pointer<->real_pointer */
+ void pointer_mapping_insert(device_ptr client_pointer, device_ptr real_pointer)
+ {
+ pair<PtrMap::iterator,bool> mapins;
+
+ /* insert mapping from client pointer to our real device pointer */
+ mapins = ptr_map.insert(PtrMap::value_type(client_pointer, real_pointer));
+ assert(mapins.second);
+
+ /* insert reverse mapping from real our device pointer to client pointer */
+ mapins = ptr_imap.insert(PtrMap::value_type(real_pointer, client_pointer));
+ assert(mapins.second);
+ }
+
+ device_ptr device_ptr_from_client_pointer(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+ return i->second;
+ }
+
+ device_ptr device_ptr_from_client_pointer_erase(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+
+ device_ptr result = i->second;
+ /* erase the mapping */
+ ptr_map.erase(i);
+
+ /* erase the reverse mapping */
+ PtrMap::iterator irev = ptr_imap.find(result);
+ assert(irev != ptr_imap.end());
+ ptr_imap.erase(irev);
+
+ /* erase the data vector */
+ DataMap::iterator idata = mem_data.find(client_pointer);
+ assert(idata != mem_data.end());
+ mem_data.erase(idata);
+
+ return result;
+ }
+
+ /* note that the lock must be already acquired upon entry.
+ * This is necessary because the caller often peeks at
+ * the header and delegates control to here when it doesn't
+ * specifically handle the current RPC.
+ * The lock must be unlocked before returning */
+ void process(RPCReceive& rcv, thread_scoped_lock &lock)
+ {
if(rcv.name == "mem_alloc") {
MemoryType type;
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
rcv.read(type);
- /* todo: CPU needs mem.data_pointer */
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
- remote_pointer = mem.device_pointer;
+ /* create a memory buffer for the device buffer */
+ size_t data_size = mem.memory_size();
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem_data[remote_pointer] = vector<uint8_t>();
- mem_data[remote_pointer].resize(mem.memory_size());
- if(mem.memory_size())
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ if(data_size)
+ mem.data_pointer = (device_ptr)&(data_v[0]);
else
mem.data_pointer = 0;
+ /* perform the allocation on the actual device */
device->mem_alloc(mem, type);
- ptr_map[remote_pointer] = mem.device_pointer;
- ptr_imap[mem.device_pointer] = remote_pointer;
+ /* store a mapping to/from client_pointer and real device pointer */
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
}
else if(rcv.name == "mem_copy_to") {
network_device_memory mem;
rcv.read(mem);
+ lock.unlock();
- device_ptr remote_pointer = mem.device_pointer;
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ device_ptr client_pointer = mem.device_pointer;
- rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ DataVector &data_v = data_vector_find(client_pointer);
- mem.device_pointer = ptr_map[remote_pointer];
+ size_t data_size = mem.memory_size();
+ /* get pointer to memory buffer for device buffer */
+ mem.data_pointer = (device_ptr)&data_v[0];
+
+ /* copy data from network into memory buffer */
+ rcv.read_buffer((uint8_t*)mem.data_pointer, data_size);
+
+ /* translate the client pointer to a real device pointer */
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ /* copy the data from the memory buffer to the device buffer */
device->mem_copy_to(mem);
}
else if(rcv.name == "mem_copy_from") {
@@ -314,37 +482,47 @@ protected:
rcv.read(h);
rcv.read(elem);
- device_ptr remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[remote_pointer];
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ device_ptr client_pointer = mem.device_pointer;
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ DataVector &data_v = data_vector_find(client_pointer);
+
+ mem.data_pointer = (device_ptr)&(data_v[0]);
device->mem_copy_from(mem, y, w, h, elem);
+ size_t data_size = mem.memory_size();
+
RPCSend snd(socket);
snd.write();
- snd.write_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ snd.write_buffer((uint8_t*)mem.data_pointer, data_size);
+ lock.unlock();
}
else if(rcv.name == "mem_zero") {
network_device_memory mem;
rcv.read(mem);
- device_ptr remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ lock.unlock();
+
+ device_ptr client_pointer = mem.device_pointer;
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ DataVector &data_v = data_vector_find(client_pointer);
+
+ mem.data_pointer = (device_ptr)&(data_v[0]);
device->mem_zero(mem);
}
else if(rcv.name == "mem_free") {
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
- remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- ptr_map.erase(remote_pointer);
- ptr_imap.erase(mem.device_pointer);
- mem_data.erase(remote_pointer);
+ mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
device->mem_free(mem);
}
@@ -357,6 +535,7 @@ protected:
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
+ lock.unlock();
device->const_copy_to(name_string.c_str(), &host_vector[0], size);
}
@@ -365,53 +544,76 @@ protected:
string name;
bool interpolation;
bool periodic;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(name);
rcv.read(mem);
rcv.read(interpolation);
rcv.read(periodic);
+ lock.unlock();
+
+ client_pointer = mem.device_pointer;
+
+ size_t data_size = mem.memory_size();
- remote_pointer = mem.device_pointer;
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem_data[remote_pointer] = vector<uint8_t>();
- mem_data[remote_pointer].resize(mem.memory_size());
- if(mem.memory_size())
- mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ if(data_size)
+ mem.data_pointer = (device_ptr)&(data_v[0]);
else
mem.data_pointer = 0;
- rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ rcv.read_buffer((uint8_t*)mem.data_pointer, data_size);
device->tex_alloc(name.c_str(), mem, interpolation, periodic);
- ptr_map[remote_pointer] = mem.device_pointer;
- ptr_imap[mem.device_pointer] = remote_pointer;
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
}
else if(rcv.name == "tex_free") {
network_device_memory mem;
- device_ptr remote_pointer;
+ device_ptr client_pointer;
rcv.read(mem);
+ lock.unlock();
- remote_pointer = mem.device_pointer;
- mem.device_pointer = ptr_map[mem.device_pointer];
- ptr_map.erase(remote_pointer);
- ptr_map.erase(mem.device_pointer);
- mem_data.erase(remote_pointer);
+ client_pointer = mem.device_pointer;
+
+ mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
device->tex_free(mem);
}
+ else if(rcv.name == "load_kernels") {
+ bool experimental;
+ rcv.read(experimental);
+
+ bool result;
+ result = device->load_kernels(experimental);
+ RPCSend snd(socket);
+ snd.add(result);
+ snd.write();
+ lock.unlock();
+ }
else if(rcv.name == "task_add") {
DeviceTask task;
rcv.read(task);
+ lock.unlock();
+
+ if(task.buffer)
+ task.buffer = device_ptr_from_client_pointer(task.buffer);
+
+ if(task.rgba_half)
+ task.rgba_half = device_ptr_from_client_pointer(task.rgba_half);
+
+ if(task.rgba_byte)
+ task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte);
+
+ if(task.shader_input)
+ task.shader_input = device_ptr_from_client_pointer(task.shader_input);
+
+ if(task.shader_output)
+ task.shader_output = device_ptr_from_client_pointer(task.shader_output);
- if(task.buffer) task.buffer = ptr_map[task.buffer];
- if(task.rgba_byte) task.rgba_byte = ptr_map[task.rgba_byte];
- if(task.rgba_half) task.rgba_half = ptr_map[task.rgba_half];
- if(task.shader_input) task.shader_input = ptr_map[task.shader_input];
- if(task.shader_output) task.shader_output = ptr_map[task.shader_output];
task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
@@ -422,14 +624,44 @@ protected:
device->task_add(task);
}
else if(rcv.name == "task_wait") {
+ lock.unlock();
+
+ blocked_waiting = true;
device->task_wait();
+ blocked_waiting = false;
+ lock.lock();
RPCSend snd(socket, "task_wait_done");
snd.write();
+ lock.unlock();
}
else if(rcv.name == "task_cancel") {
+ lock.unlock();
device->task_cancel();
}
+ else if(rcv.name == "acquire_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ rcv.read(entry.tile);
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if(rcv.name == "acquire_tile_none") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if(rcv.name == "release_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else {
+ cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n";
+ lock.unlock();
+ }
}
bool task_acquire_tile(Device *device, RenderTile& tile)
@@ -441,23 +673,34 @@ protected:
RPCSend snd(socket, "acquire_tile");
snd.write();
- while(1) {
- RPCReceive rcv(socket);
+ do {
+ if(blocked_waiting)
+ listen_step();
- if(rcv.name == "acquire_tile") {
- rcv.read(tile);
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
- if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
- if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
+ if(!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
- result = true;
- break;
+ if(entry.name == "acquire_tile") {
+ tile = entry.tile;
+
+ if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
+ if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
+
+ result = true;
+ break;
+ }
+ else if(entry.name == "acquire_tile_none") {
+ break;
+ }
+ else {
+ cout << "Error: unexpected acquire RPC receive call \"" + entry.name + "\"\n";
+ }
}
- else if(rcv.name == "acquire_tile_none")
- break;
- else
- process(rcv);
- }
+ } while(acquire_queue.empty() && !stop);
return result;
}
@@ -479,18 +722,34 @@ protected:
if(tile.buffer) tile.buffer = ptr_imap[tile.buffer];
if(tile.rng_state) tile.rng_state = ptr_imap[tile.rng_state];
- RPCSend snd(socket, "release_tile");
- snd.add(tile);
- snd.write();
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, "release_tile");
+ snd.add(tile);
+ snd.write();
+ lock.unlock();
+ }
- while(1) {
- RPCReceive rcv(socket);
+ do {
+ if(blocked_waiting)
+ listen_step();
- if(rcv.name == "release_tile")
- break;
- else
- process(rcv);
- }
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
+
+ if(!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
+
+ if(entry.name == "release_tile") {
+ lock.unlock();
+ break;
+ }
+ else {
+ cout << "Error: unexpected release RPC receive call \"" + entry.name + "\"\n";
+ }
+ }
+ } while(acquire_queue.empty() && !stop);
}
bool task_get_cancel()
@@ -503,11 +762,20 @@ protected:
tcp::socket& socket;
/* mapping of remote to local pointer */
- map<device_ptr, device_ptr> ptr_map;
- map<device_ptr, device_ptr> ptr_imap;
- map<device_ptr, vector<uint8_t> > mem_data;
+ PtrMap ptr_map;
+ PtrMap ptr_imap;
+ DataMap mem_data;
+
+ struct AcquireEntry {
+ string name;
+ RenderTile tile;
+ };
thread_mutex acquire_mutex;
+ list<AcquireEntry> acquire_queue;
+
+ bool stop;
+ bool blocked_waiting;
/* todo: free memory and device (osl) on network error */
};
@@ -540,7 +808,8 @@ void Device::server_run()
}
}
+CCL_NAMESPACE_END
+
#endif
-CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index db399cf4240..d639450b9ea 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -28,6 +28,8 @@
#include <boost/thread.hpp>
#include <iostream>
+#include <sstream>
+#include <deque>
#include "buffers.h"
@@ -70,12 +72,12 @@ public:
: name(name_), socket(socket_), archive(archive_stream), sent(false)
{
archive & name_;
+
+ fprintf(stderr, "rpc send %s\n", name.c_str());
}
~RPCSend()
{
- if(!sent)
- fprintf(stderr, "Error: RPC %s not sent\n", name.c_str());
}
void add(const device_memory& mem)
@@ -98,13 +100,14 @@ public:
archive & task.offset & task.stride;
archive & task.shader_input & task.shader_output & task.shader_eval_type;
archive & task.shader_x & task.shader_w;
+ archive & task.need_finish_queue;
}
void add(const RenderTile& tile)
{
archive & tile.x & tile.y & tile.w & tile.h;
archive & tile.start_sample & tile.num_samples & tile.sample;
- archive & tile.offset & tile.stride;
+ archive & tile.resolution & tile.offset & tile.stride;
archive & tile.buffer & tile.rng_state;
}
@@ -178,6 +181,7 @@ public:
size_t data_size;
if((header_stream >> hex >> data_size)) {
+
vector<char> data(data_size);
size_t len = boost::asio::read(socket, boost::asio::buffer(data));
@@ -191,15 +195,19 @@ public:
archive = new boost::archive::text_iarchive(*archive_stream);
*archive & name;
+ fprintf(stderr, "rpc receive %s\n", name.c_str());
+ }
+ else {
+ cout << "Network receive error: data size doesn't match header\n";
}
- else
- cout << "Network receive error: data size doens't match header\n";
}
- else
+ else {
cout << "Network receive error: can't decode data size from header\n";
+ }
}
- else
+ else {
cout << "Network receive error: invalid header size\n";
+ }
}
~RPCReceive()
@@ -235,9 +243,10 @@ public:
*archive & type & task.x & task.y & task.w & task.h;
*archive & task.rgba_byte & task.rgba_half & task.buffer & task.sample & task.num_samples;
- *archive & task.resolution & task.offset & task.stride;
+ *archive & task.offset & task.stride;
*archive & task.shader_input & task.shader_output & task.shader_eval_type;
*archive & task.shader_x & task.shader_w;
+ *archive & task.need_finish_queue;
task.type = (DeviceTask::Type)type;
}
@@ -247,7 +256,7 @@ public:
*archive & tile.x & tile.y & tile.w & tile.h;
*archive & tile.start_sample & tile.num_samples & tile.sample;
*archive & tile.resolution & tile.offset & tile.stride;
- *archive & tile.buffer & tile.rng_state & tile.rgba_byte & tile.rgba_half;
+ *archive & tile.buffer & tile.rng_state;
tile.buffers = NULL;
}
@@ -303,12 +312,12 @@ public:
delete work;
}
- list<string> get_server_list()
+ vector<string> get_server_list()
{
- list<string> result;
+ vector<string> result;
mutex.lock();
- result = servers;
+ result = vector<string>(servers.begin(), servers.end());
mutex.unlock();
return result;
@@ -333,11 +342,8 @@ private:
mutex.lock();
/* add address if it's not already in the list */
- bool found = false;
-
- foreach(string& server, servers)
- if(server == address)
- found = true;
+ bool found = std::find(servers.begin(), servers.end(),
+ address) != servers.end();
if(!found)
servers.push_back(address);
@@ -393,10 +399,21 @@ private:
/* buffer and endpoint for receiving messages */
char receive_buffer[256];
boost::asio::ip::udp::endpoint receive_endpoint;
+
+ // os, version, devices, status, host name, group name, ip as far as fields go
+ struct ServerInfo {
+ string cycles_version;
+ string os;
+ int device_count;
+ string status;
+ string host_name;
+ string group_name;
+ string host_addr;
+ };
/* collection of server addresses in list */
bool collect_servers;
- list<string> servers;
+ vector<string> servers;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 11c7bc6f099..98d3b07b7ee 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -423,9 +423,8 @@ public:
}
OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_)
- : Device(stats)
+ : Device(info, stats, background_)
{
- background = background_;
cpPlatform = NULL;
cdDevice = NULL;
cxContext = NULL;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 56ba0e08743..39444b91131 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -190,13 +190,18 @@ endif()
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
-add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS})
-
if(WITH_CYCLES_OPTIMIZED_KERNEL)
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}")
endif()
+if(WITH_CYCLES_OPTIMIZED_KERNEL_SSE41)
+ set_source_files_properties(kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ list(APPEND SRC kernel_sse41.cpp)
+endif()
+
+add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS})
+
if(WITH_CYCLES_CUDA)
add_dependencies(cycles_kernel cycles_kernel_cuda)
endif()
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index f30b30c8c76..f4932568c1f 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -53,11 +53,6 @@ ccl_device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const f
ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::volume_eval_phase(sc, omega_in, omega_out);
-#endif
-
float3 eval;
switch(sc->type) {
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 361f5b0856d..105a3887da0 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -61,6 +61,15 @@ void kernel_cpu_sse3_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, floa
float sample_scale, int x, int y, int offset, int stride);
void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i);
+
+void kernel_cpu_sse41_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
+ int sample, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+ float sample_scale, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+ float sample_scale, int x, int y, int offset, int stride);
+void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output,
+ int type, int i);
#endif
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
index ababad28f35..0e39c489fbc 100644
--- a/intern/cycles/kernel/kernel_primitive.h
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -89,6 +89,25 @@ ccl_device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
return uv;
}
+ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
+{
+ /* storing ptex data as attributes is not memory efficient but simple for tests */
+ AttributeElement elem_face_id, elem_uv;
+ int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id);
+ int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv);
+
+ if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND)
+ return false;
+
+ float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
+ float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL);
+
+ *uv = make_float2(uv3.x, uv3.y);
+ *face_id = (int)face_id_f;
+
+ return true;
+}
+
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 77154ce3aef..dbc705ea791 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -764,11 +764,6 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ccl_device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc)
{
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::emissive_eval(sd, sc);
-#endif
-
return emissive_simple_eval(sd->Ng, sd->I);
}
diff --git a/intern/cycles/kernel/kernel_sse41.cpp b/intern/cycles/kernel/kernel_sse41.cpp
new file mode 100644
index 00000000000..0c68fd3651b
--- /dev/null
+++ b/intern/cycles/kernel/kernel_sse41.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+#ifdef WITH_OPTIMIZED_KERNEL
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+#define __KERNEL_SSE2__
+#define __KERNEL_SSE3__
+#define __KERNEL_SSSE3__
+#define __KERNEL_SSE41__
+#endif
+
+#include "kernel.h"
+#include "kernel_compat_cpu.h"
+#include "kernel_math.h"
+#include "kernel_types.h"
+#include "kernel_globals.h"
+#include "kernel_film.h"
+#include "kernel_path.h"
+#include "kernel_displace.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Path Tracing */
+
+void kernel_cpu_sse41_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
+{
+#ifdef __BRANCHED_PATH__
+ if(kernel_data.integrator.branched)
+ kernel_branched_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
+ else
+#endif
+ kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
+}
+
+/* Film */
+
+void kernel_cpu_sse41_convert_to_byte(KernelGlobals *kg, uchar4 *rgba, float *buffer, float sample_scale, int x, int y, int offset, int stride)
+{
+ kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+void kernel_cpu_sse41_convert_to_half_float(KernelGlobals *kg, uchar4 *rgba, float *buffer, float sample_scale, int x, int y, int offset, int stride)
+{
+ kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+/* Shader Evaluate */
+
+void kernel_cpu_sse41_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i)
+{
+ kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
+}
+
+CCL_NAMESPACE_END
+
+#endif
+
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 3371c580c71..51a49348810 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -436,6 +436,8 @@ typedef enum AttributeStandard {
ATTR_STD_MOTION_POST,
ATTR_STD_PARTICLE,
ATTR_STD_CURVE_INTERCEPT,
+ ATTR_STD_PTEX_FACE_ID,
+ ATTR_STD_PTEX_UV,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index eed4446cddc..2facced0914 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -46,14 +46,9 @@ using namespace OSL;
/// to return a color in background shaders. No methods,
/// only the weight is taking into account
///
-class GenericBackgroundClosure : public OSL::BackgroundClosure {
+class GenericBackgroundClosure : public CClosurePrimitive {
public:
- GenericBackgroundClosure() {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "background"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ GenericBackgroundClosure() : CClosurePrimitive(Background) {}
};
/// Holdout closure
@@ -63,14 +58,9 @@ public:
/// point. No parameters, only the weight will be
/// used
///
-class HoldoutClosure : ClosurePrimitive {
+class HoldoutClosure : CClosurePrimitive {
public:
- HoldoutClosure () : ClosurePrimitive(Holdout) {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "holdout"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ HoldoutClosure () : CClosurePrimitive(Holdout) {}
};
/// ambient occlusion closure
@@ -79,14 +69,9 @@ public:
/// to return a color in ambient occlusion shaders. No methods,
/// only the weight is taking into account
///
-class AmbientOcclusionClosure : public ClosurePrimitive {
+class AmbientOcclusionClosure : public CClosurePrimitive {
public:
- AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {}
-
- void setup() {};
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "ambient_occlusion"; }
- void print_on(std::ostream &out) const { out << name() << " ()"; }
+ AmbientOcclusionClosure () : CClosurePrimitive(AmbientOcclusion) {}
};
ClosureParam *closure_background_params()
@@ -98,7 +83,7 @@ ClosureParam *closure_background_params()
return params;
}
-CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
+CCLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
ClosureParam *closure_holdout_params()
{
@@ -108,7 +93,7 @@ ClosureParam *closure_holdout_params()
return params;
}
-CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
+CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
ClosureParam *closure_ambient_occlusion_params()
{
@@ -119,7 +104,7 @@ ClosureParam *closure_ambient_occlusion_params()
return params;
}
-CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
+CCLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index a320bea118a..8f9c2efd470 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -46,12 +46,11 @@ using namespace OSL;
class DiffuseRampClosure : public CBSDFClosure {
public:
- DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE) {}
Color3 colors[8];
float3 fcolors[8];
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "diffuse_ramp"; }
+ DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE)
+ {}
void setup()
{
@@ -62,21 +61,11 @@ public:
fcolors[i] = TO_FLOAT3(colors[i]);
}
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
void blur(float roughness)
{
bsdf_diffuse_ramp_blur(&sc, roughness);
}
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
-
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
@@ -109,7 +98,7 @@ ClosureParam *closure_bsdf_diffuse_ramp_params()
return params;
}
-CLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure)
+CCLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index ef656ee7d5f..c5851747b54 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -45,12 +45,11 @@ using namespace OSL;
class PhongRampClosure : public CBSDFClosure {
public:
- PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY) {}
Color3 colors[8];
float3 fcolors[8];
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "phong_ramp"; }
+ PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY)
+ {}
void setup()
{
@@ -61,21 +60,11 @@ public:
fcolors[i] = TO_FLOAT3(colors[i]);
}
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
void blur(float roughness)
{
bsdf_phong_ramp_blur(&sc, roughness);
}
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
-
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
@@ -109,7 +98,7 @@ ClosureParam *closure_bsdf_phong_ramp_params()
return params;
}
-CLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure)
+CCLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 7d9fa81dbdd..02935542c56 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -50,18 +50,9 @@ using namespace OSL;
/// outer_angle limit. It can also behave as a lambertian emitter
/// if the provided angles are PI/2, which is the default
///
-class GenericEmissiveClosure : public EmissiveClosure {
+class GenericEmissiveClosure : public CClosurePrimitive {
public:
- GenericEmissiveClosure() { }
-
- void setup() {}
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "emission"; }
-
- void print_on(std::ostream &out) const
- {
- out << name() << "()";
- }
+ GenericEmissiveClosure() : CClosurePrimitive(Emissive) { }
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
{
@@ -92,7 +83,7 @@ ClosureParam *closure_emission_params()
return params;
}
-CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
+CCLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 975967c0bbb..94337290d20 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -51,24 +51,14 @@ using namespace OSL;
class CubicBSSRDFClosure : public CBSSRDFClosure {
public:
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "bssrdf_cubic"; }
+ CubicBSSRDFClosure()
+ {}
void setup()
{
sc.type = CLOSURE_BSSRDF_CUBIC_ID;
sc.data0 = fabsf(average(radius));
}
-
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
};
ClosureParam *closure_bssrdf_cubic_params()
@@ -96,30 +86,20 @@ ClosureParam *closure_bssrdf_cubic_extended_params()
return params;
}
-CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
+CCLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
/* Gaussian */
class GaussianBSSRDFClosure : public CBSSRDFClosure {
public:
- size_t memsize() const { return sizeof(*this); }
- const char *name() const { return "bssrdf_gaussian"; }
+ GaussianBSSRDFClosure()
+ {}
void setup()
{
sc.type = CLOSURE_BSSRDF_GAUSSIAN_ID;
sc.data0 = fabsf(average(radius));
}
-
- bool mergeable(const ClosurePrimitive *other) const
- {
- return false;
- }
-
- void print_on(std::ostream &out) const
- {
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
- }
};
ClosureParam *closure_bssrdf_gaussian_params()
@@ -146,7 +126,7 @@ ClosureParam *closure_bssrdf_gaussian_extended_params()
return params;
}
-CLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
+CCLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h
index fc1a4c587cc..6aee2c28ea8 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.h
+++ b/intern/cycles/kernel/osl/osl_bssrdf.h
@@ -37,20 +37,20 @@
#include <OSL/oslexec.h>
#include <OSL/genclosure.h>
+#include "osl_closures.h"
+
#include "kernel_types.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
-class CBSSRDFClosure : public OSL::ClosurePrimitive {
+class CBSSRDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
float3 radius;
- CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF) { memset(&sc, 0, sizeof(sc)); }
- ~CBSSRDFClosure() { }
-
+ CBSSRDFClosure() : CClosurePrimitive(BSSRDF) { }
int scattering() const { return LABEL_DIFFUSE; }
};
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 221406a1716..340e4492584 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -171,25 +171,16 @@ BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
/* Registration */
-static void generic_closure_setup(OSL::RendererServices *, int id, void *data)
-{
- assert(data);
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)data;
- prim->setup();
-}
-
-static bool generic_closure_compare(int id, const void *dataA, const void *dataB)
-{
- assert(dataA && dataB);
-
- OSL::ClosurePrimitive *primA = (OSL::ClosurePrimitive *)dataA;
- OSL::ClosurePrimitive *primB = (OSL::ClosurePrimitive *)dataB;
- return primA->mergeable(primB);
-}
-
static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
{
- ss->register_closure(name, id, params, prepare, generic_closure_setup, generic_closure_compare);
+ /* 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
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 6632c2c57e5..b6c38e01b23 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -66,36 +66,52 @@ void closure_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
-enum {
- AmbientOcclusion = 100
-};
-
-#define CLOSURE_PREPARE(name, classname) \
+#define CCLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \
{ \
memset(data, 0, sizeof(classname)); \
new (data) classname(); \
}
-#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname)
+#define CCLOSURE_PREPARE_STATIC(name, classname) static CCLOSURE_PREPARE(name, classname)
#define CLOSURE_FLOAT3_PARAM(st, fld) \
- { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
+ { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
+/* Closure */
+
+class CClosurePrimitive {
+public:
+ enum Category {
+ BSDF, ///< Reflective and/or transmissive surface
+ BSSRDF, ///< Sub-surface light transfer
+ Emissive, ///< Light emission
+ Background, ///< Background emission
+ Volume, ///< Volume scattering
+ Holdout, ///< Holdout from alpha
+ AmbientOcclusion, ///< Ambient occlusion
+ };
+
+ CClosurePrimitive (Category category_) : category (category_) {}
+ virtual ~CClosurePrimitive() {}
+ virtual void setup() {}
+
+ Category category;
+};
+
/* BSDF */
-class CBSDFClosure : public OSL::ClosurePrimitive {
+class CBSDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
- CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF),
+ CBSDFClosure(int scattering) : CClosurePrimitive(BSDF),
m_scattering_label(scattering), m_shaderdata_flag(0)
- { memset(&sc, 0, sizeof(sc)); }
- ~CBSDFClosure() { }
+ {}
int scattering() const { return m_scattering_label; }
int shaderdata_flag() const { return m_shaderdata_flag; }
@@ -119,9 +135,9 @@ protected:
\
class Upper##Closure : public CBSDFClosure { \
public: \
- Upper##Closure() : CBSDFClosure(TYPE) {} \
- size_t memsize() const { return sizeof(*this); } \
- const char *name() const { return #lower; } \
+ Upper##Closure() : CBSDFClosure(TYPE) \
+ { \
+ } \
\
void setup() \
{ \
@@ -129,21 +145,11 @@ public: \
m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
} \
\
- bool mergeable(const ClosurePrimitive *other) const \
- { \
- return false; \
- } \
- \
void blur(float roughness) \
{ \
bsdf_##svmlower##_blur(&sc, roughness); \
} \
\
- void print_on(std::ostream &out) const \
- { \
- out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; \
- } \
-\
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
return bsdf_##svmlower##_eval_reflect(&sc, omega_out, omega_in, &pdf); \
@@ -178,7 +184,7 @@ static ClosureParam *bsdf_##lower##_params() \
return params; \
} \
\
-CLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
+CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 309f5ded96d..d7d3301c0b0 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -44,6 +44,10 @@
#include "kernel_camera.h"
#include "kernel_shader.h"
+#ifdef WITH_PTEX
+#include <Ptexture.h>
+#endif
+
CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
@@ -98,10 +102,18 @@ OSLRenderServices::OSLRenderServices()
{
kernel_globals = NULL;
osl_ts = NULL;
+
+#ifdef WITH_PTEX
+ size_t maxmem = 16384 * 1024;
+ ptex_cache = PtexCache::create(0, maxmem);
+#endif
}
OSLRenderServices::~OSLRenderServices()
{
+#ifdef WITH_PTEX
+ ptex_cache->release();
+#endif
}
void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_, OSL::TextureSystem *osl_ts_)
@@ -776,6 +788,45 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
OSL::TextureSystem *ts = osl_ts;
ShaderData *sd = (ShaderData *)(sg->renderstate);
KernelGlobals *kg = sd->osl_globals;
+
+#ifdef WITH_PTEX
+ /* todo: this is just a quick hack, only works with particular files and options */
+ if(string_endswith(filename.string(), ".ptx")) {
+ float2 uv;
+ int faceid;
+
+ if(!primitive_ptex(kg, sd, &uv, &faceid))
+ return false;
+
+ float u = uv.x;
+ float v = uv.y;
+ float dudx = 0.0f;
+ float dvdx = 0.0f;
+ float dudy = 0.0f;
+ float dvdy = 0.0f;
+
+ Ptex::String error;
+ PtexPtr<PtexTexture> r(ptex_cache->get(filename.c_str(), error));
+
+ if(!r) {
+ //std::cerr << error.c_str() << std::endl;
+ return false;
+ }
+
+ bool mipmaplerp = false;
+ float sharpness = 1.0f;
+ PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness);
+ PtexPtr<PtexFilter> f(PtexFilter::getFilter(r, opts));
+
+ f->eval(result, options.firstchannel, options.nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy);
+
+ for(int c = r->numChannels(); c < options.nchannels; c++)
+ result[c] = result[0];
+
+ return true;
+ }
+#endif
+
OSLThreadData *tdata = kg->osl_tdata;
OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info;
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index f62895047b3..21609621b1d 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -28,6 +28,10 @@
#include <OSL/oslexec.h>
#include <OSL/oslclosure.h>
+#ifdef WITH_PTEX
+class PtexCache;
+#endif
+
CCL_NAMESPACE_BEGIN
class Object;
@@ -148,6 +152,9 @@ public:
private:
KernelGlobals *kernel_globals;
OSL::TextureSystem *osl_ts;
+#ifdef WITH_PTEX
+ PtexCache *ptex_cache;
+#endif
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 18e8fee4348..f2be61eb535 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -146,7 +146,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if (prim) {
ShaderClosure sc;
@@ -156,8 +156,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
sc.weight = weight;
#endif
- switch (prim->category()) {
- case OSL::ClosurePrimitive::BSDF: {
+ prim->setup();
+
+ switch (prim->category) {
+ case CClosurePrimitive::BSDF: {
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
int scattering = bsdf->scattering();
@@ -191,7 +193,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Emissive: {
+ case CClosurePrimitive::Emissive: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -208,7 +210,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case AmbientOcclusion: {
+ case CClosurePrimitive::AmbientOcclusion: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -224,7 +226,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Holdout: {
+ case CClosurePrimitive::Holdout: {
sc.sample_weight = 0.0f;
sc.type = CLOSURE_HOLDOUT_ID;
sc.data0 = 0.0f;
@@ -237,7 +239,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::BSSRDF: {
+ case CClosurePrimitive::BSSRDF: {
CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
float sample_weight = fabsf(average(weight));
@@ -280,10 +282,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
}
break;
}
- case OSL::ClosurePrimitive::Debug:
- break; /* not implemented */
- case OSL::ClosurePrimitive::Background:
- case OSL::ClosurePrimitive::Volume:
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::Volume:
break; /* not relevant */
}
}
@@ -332,9 +332,9 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
- if (prim && prim->category() == OSL::ClosurePrimitive::Background)
+ if (prim && prim->category == CClosurePrimitive::Background)
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
return TO_FLOAT3(comp->w);
#else
@@ -387,7 +387,7 @@ static void flatten_volume_closure_tree(ShaderData *sd,
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if (prim) {
ShaderClosure sc;
@@ -397,8 +397,10 @@ static void flatten_volume_closure_tree(ShaderData *sd,
sc.weight = weight;
#endif
- switch (prim->category()) {
- case OSL::ClosurePrimitive::Volume: {
+ prim->setup();
+
+ switch (prim->category) {
+ case CClosurePrimitive::Volume: {
/* sample weight */
float sample_weight = fabsf(average(weight));
@@ -413,13 +415,13 @@ static void flatten_volume_closure_tree(ShaderData *sd,
sd->closure[sd->num_closure++] = sc;
break;
}
- case OSL::ClosurePrimitive::Holdout:
- case OSL::ClosurePrimitive::Debug:
+ case CClosurePrimitive::Holdout:
break; /* not implemented */
- case OSL::ClosurePrimitive::Background:
- case OSL::ClosurePrimitive::BSDF:
- case OSL::ClosurePrimitive::Emissive:
- case OSL::ClosurePrimitive::BSSRDF:
+ case CClosurePrimitive::Background:
+ case CClosurePrimitive::BSDF:
+ case CClosurePrimitive::Emissive:
+ case CClosurePrimitive::BSSRDF:
+ case CClosurePrimitive::AmbientOcclusion:
break; /* not relevant */
}
}
@@ -509,25 +511,6 @@ void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
bsdf->blur(roughness);
}
-/* Emissive Closure */
-
-float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
-{
- OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
- OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
-
- return TO_FLOAT3(emissive_eval);
-}
-
-/* Volume Closure */
-
-float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
-{
- OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
- OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
- return TO_FLOAT3(volume_eval) * sc->weight;
-}
-
/* Attributes */
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 777ecb6af81..2520b703ab7 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -66,11 +66,6 @@ public:
const float3& omega_in, float& pdf);
static void bsdf_blur(ShaderClosure *sc, float roughness);
- static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
-
- static float3 volume_eval_phase(const ShaderClosure *sc,
- const float3 omega_in, const float3 omega_out);
-
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 47c5dc27f2b..d1d1222af44 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -412,13 +412,27 @@ matrix transpose (matrix m) BUILTIN;
// Pattern generation
-float step (float edge, float x) BUILTIN;
color step (color edge, color x) BUILTIN;
point step (point edge, point x) BUILTIN;
vector step (vector edge, vector x) BUILTIN;
normal step (normal edge, normal x) BUILTIN;
+float step (float edge, float x) BUILTIN;
float smoothstep (float edge0, float edge1, float x) BUILTIN;
+float aastep (float edge, float s, float dedge, float ds) {
+ // Box filtered AA step
+ float width = fabs(dedge) + fabs(ds);
+ float halfwidth = 0.5*width;
+ float e1 = edge-halfwidth;
+ return (s <= e1) ? 0.0 : ((s >= (edge+halfwidth)) ? 1.0 : (s-e1)/width);
+}
+float aastep (float edge, float s, float ds) {
+ return aastep (edge, s, filterwidth(edge), ds);
+}
+float aastep (float edge, float s) {
+ return aastep (edge, s, filterwidth(edge), filterwidth(s));
+}
+
// Derivatives and area operators
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index bb70a3faa2a..0a3d576cfe1 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -39,10 +39,12 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
{
uint blend_offset = node.y;
uint blend_value = node.z;
- float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
- uint type, out_offset;
- decode_node_uchar4(node.w, &type, &out_offset, NULL, NULL);
+ uint type, normal_offset, out_offset;
+ decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL);
+
+ float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
+ float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): sd->N;
float f;
@@ -50,10 +52,10 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
float eta = fmaxf(1.0f - blend, 1e-5f);
eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
- f = fresnel_dielectric_cos(dot(sd->I, sd->N), eta);
+ f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
}
else {
- f = fabsf(dot(sd->I, sd->N));
+ f = fabsf(dot(sd->I, normal_in));
if(blend != 0.5f) {
blend = clamp(blend, 0.0f, 1.0f-1e-5f);
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 319616450e1..6640439eca9 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -147,6 +147,10 @@ const char *Attribute::standard_name(AttributeStandard std)
return "particle";
else if(std == ATTR_STD_CURVE_INTERCEPT)
return "curve_intercept";
+ else if(std == ATTR_STD_PTEX_FACE_ID)
+ return "ptex_face_id";
+ else if(std == ATTR_STD_PTEX_UV)
+ return "ptex_uv";
return "";
}
@@ -246,6 +250,12 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_MOTION_POST:
attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
break;
+ case ATTR_STD_PTEX_FACE_ID:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_PTEX_UV:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
default:
assert(0);
break;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 4919222e81c..fcc92b641fd 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -217,6 +217,21 @@ ShaderNode *ImageTextureNode::clone() const
return node;
}
+void ImageTextureNode::attributes(AttributeRequestSet *attributes)
+{
+#ifdef WITH_PTEX
+ /* todo: avoid loading other texture coordinates when using ptex,
+ * and hide texture coordinate socket in the UI */
+ if (string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
+#endif
+
+ ShaderNode::attributes(attributes);
+}
+
void ImageTextureNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector_in = input("Vector");
@@ -352,6 +367,19 @@ ShaderNode *EnvironmentTextureNode::clone() const
return node;
}
+void EnvironmentTextureNode::attributes(AttributeRequestSet *attributes)
+{
+#ifdef WITH_PTEX
+ if (string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
+#endif
+
+ ShaderNode::attributes(attributes);
+}
+
void EnvironmentTextureNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector_in = input("Vector");
@@ -3198,8 +3226,12 @@ LayerWeightNode::LayerWeightNode()
void LayerWeightNode::compile(SVMCompiler& compiler)
{
+ ShaderInput *normal_in = input("Normal");
ShaderInput *blend_in = input("Blend");
+ if(normal_in->link)
+ compiler.stack_assign(normal_in);
+
if(blend_in->link)
compiler.stack_assign(blend_in);
@@ -3207,14 +3239,14 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!fresnel_out->links.empty()) {
compiler.stack_assign(fresnel_out);
compiler.add_node(NODE_LAYER_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL, fresnel_out->stack_offset));
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL, normal_in->stack_offset, fresnel_out->stack_offset));
}
ShaderOutput *facing_out = output("Facing");
if(!facing_out->links.empty()) {
compiler.stack_assign(facing_out);
compiler.add_node(NODE_LAYER_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING, facing_out->stack_offset));
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING, normal_in->stack_offset, facing_out->stack_offset));
}
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 430c37158f4..d7a110af83b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -66,6 +66,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
~ImageTextureNode();
ShaderNode *clone() const;
+ void attributes(AttributeRequestSet *attributes);
ImageManager *image_manager;
int slot;
@@ -87,6 +88,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
~EnvironmentTextureNode();
ShaderNode *clone() const;
+ void attributes(AttributeRequestSet *attributes);
ImageManager *image_manager;
int slot;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index d0ed95cca34..4ed8ece0556 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -724,13 +724,17 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
} while(!nodes_done);
}
-void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
+OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
current_type = type;
+#if OSL_LIBRARY_VERSION_CODE >= 10501
+ OSL::ShadingAttribStateRef group = ss->ShaderGroupBegin(shader->name.c_str());
+#else
ss->ShaderGroupBegin(shader->name.c_str());
+#endif
ShaderNode *output = graph->output();
set<ShaderNode*> dependencies;
@@ -757,12 +761,19 @@ void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
assert(0);
ss->ShaderGroupEnd();
+
+#if OSL_LIBRARY_VERSION_CODE >= 10501
+ return group;
+#else
+ OSL::ShadingAttribStateRef group = ss->state();
+ ss->clear_state();
+ return group;
+#endif
}
void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
{
if(shader->need_update) {
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
ShaderGraph *graph = shader->graph;
ShaderNode *output = (graph)? graph->output(): NULL;
@@ -788,19 +799,13 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
/* generate surface shader */
if(shader->used && graph && output->input("Surface")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- shader->osl_surface_ref = ss->state();
+ shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- if(shader->graph_bump) {
- ss->clear_state();
- compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
- shader->osl_surface_bump_ref = ss->state();
- }
+ if(shader->graph_bump)
+ shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
else
shader->osl_surface_bump_ref = shader->osl_surface_ref;
- ss->clear_state();
-
shader->has_surface = true;
}
else {
@@ -810,21 +815,16 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
/* generate volume shader */
if(shader->used && graph && output->input("Volume")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
shader->has_volume = true;
-
- shader->osl_volume_ref = ss->state();
- ss->clear_state();
}
else
shader->osl_volume_ref = OSL::ShadingAttribStateRef();
/* generate displacement shader */
if(shader->used && graph && output->input("Displacement")->link) {
- compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
shader->has_displacement = true;
- shader->osl_displacement_ref = ss->state();
- ss->clear_state();
}
else
shader->osl_displacement_ref = OSL::ShadingAttribStateRef();
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index d6e514bdcaf..5824e2ace64 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -142,14 +142,16 @@ public:
ImageManager *image_manager;
private:
+#ifdef WITH_OSL
string id(ShaderNode *node);
- void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+ OSL::ShadingAttribStateRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
bool node_skip_input(ShaderNode *node, ShaderInput *input);
string compatible_name(ShaderNode *node, ShaderInput *input);
string compatible_name(ShaderNode *node, ShaderOutput *output);
void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input);
void generate_nodes(const set<ShaderNode*>& nodes);
+#endif
void *shadingsys;
void *manager;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 6c15849d815..0805a685467 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -95,7 +95,7 @@ Session::~Session()
wait();
}
- if(display && params.output_path != "") {
+ if(display && !params.output_path.empty()) {
tonemap();
progress.set_status("Writing Image", params.output_path);
@@ -242,7 +242,7 @@ void Session::run_gpu()
/* update scene */
update_scene();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
if(progress.get_cancel())
@@ -263,7 +263,7 @@ void Session::run_gpu()
device->task_wait();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
/* update status and timing */
@@ -283,7 +283,7 @@ void Session::run_gpu()
}
}
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -531,7 +531,7 @@ void Session::run_cpu()
/* update scene */
update_scene();
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
if(progress.get_cancel())
@@ -549,7 +549,7 @@ void Session::run_cpu()
if(!params.background)
need_tonemap = true;
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
}
@@ -571,7 +571,7 @@ void Session::run_cpu()
tonemap();
}
- if(device->error_message() != "")
+ if(!device->error_message().empty())
progress.set_cancel(device->error_message());
tiles_written = update_progressive_refine(progress.get_cancel());
@@ -592,7 +592,7 @@ void Session::run()
if(!device->load_kernels(params.experimental)) {
string message = device->error_message();
- if(message == "")
+ if(message.empty())
message = "Failed loading render kernel, see console for errors";
progress.set_status("Error", message);
@@ -796,7 +796,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
}
else {
status = substatus;
- substatus = "";
+ substatus.clear();
}
progress.set_status(status, substatus);
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index 838776d60bf..2641f6d9c0c 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -12,26 +12,17 @@ set(INC_SYS
)
set(SRC
- subd_build.cpp
subd_dice.cpp
subd_mesh.cpp
subd_patch.cpp
- subd_ring.cpp
subd_split.cpp
- subd_stencil.cpp
)
set(SRC_HEADERS
- subd_build.h
subd_dice.h
- subd_edge.h
- subd_face.h
subd_mesh.h
subd_patch.h
- subd_ring.h
subd_split.h
- subd_stencil.h
- subd_vert.h
)
include_directories(${INC})
diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp
deleted file mode 100644
index f3c2837c37c..00000000000
--- a/intern/cycles/subd/subd_build.cpp
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_mesh.h"
-#include "subd_patch.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_string.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Builder */
-
-SubdBuilder *SubdBuilder::create(bool linear)
-{
- if(linear)
- return new SubdLinearBuilder();
- else
- return new SubdAccBuilder();
-}
-
-/* Gregory ACC Stencil */
-
-class GregoryAccStencil {
-public:
- SubdFaceRing *ring;
- StencilMask stencil[20];
-
- GregoryAccStencil(SubdFaceRing *ring_)
- {
- ring = ring_;
-
- for(int i = 0; i < 20; i++)
- stencil[i].resize(ring->num_verts());
- }
-
- StencilMask& get(int i)
- {
- assert(i < 20);
- return stencil[i];
- }
-
- float& get(int i, SubdVert *vert)
- {
- assert(i < 20);
- return stencil[i][ring->vert_index(vert)];
- }
-};
-
-static float pseudoValence(SubdVert *vert)
-{
- float valence = (float)vert->valence();
-
- if(vert->is_boundary()) {
- /* we treat boundary verts as being half a closed mesh. corners are
- * special case. n = 4 for corners and n = 2*(n-1) for boundaries. */
- if(valence == 2) return 4;
- return (valence - 1)*2;
- }
-
- return valence;
-}
-
-/* Subd ACC Builder */
-
-SubdAccBuilder::SubdAccBuilder()
-{
-}
-
-SubdAccBuilder::~SubdAccBuilder()
-{
-}
-
-Patch *SubdAccBuilder::run(SubdFace *face)
-{
- SubdFaceRing ring(face, face->edge);
- GregoryAccStencil stencil(&ring);
- float3 position[20];
-
- computeCornerStencil(&ring, &stencil);
- computeEdgeStencil(&ring, &stencil);
- computeInteriorStencil(&ring, &stencil);
-
- ring.evaluate_stencils(position, stencil.stencil, 20);
-
- if(face->num_edges() == 3) {
- GregoryTrianglePatch *patch = new GregoryTrianglePatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
- else if(face->num_edges() == 4) {
- GregoryQuadPatch *patch = new GregoryQuadPatch();
- memcpy(patch->hull, position, sizeof(float3)*20);
- return patch;
- }
-
- assert(0); /* n-gons should have been split already */
- return NULL;
-}
-
-/* Gregory Patch */
-
-void SubdAccBuilder::computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- if(vert->is_boundary()) {
- /* compute vertex limit position */
- SubdEdge *edge0 = vert->edge;
- SubdEdge *edge1 = vert->edge->prev;
-
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
- assert(edge1->face == NULL);
- assert(edge1->from() != vert);
-
- stencil->get(cid, vert) = 2.0f/3.0f;
- stencil->get(cid, edge0->to()) = 1.0f/6.0f;
- stencil->get(cid, edge1->from()) = 1.0f/6.0f;
-
- assert(stencil->get(cid).is_normalized());
- }
- else {
- stencil->get(cid, vert) = 3.0f*valence*valence;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance()) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- stencil->get(cid, edge->to()) = 12.0f;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* distribute weight to all verts */
- stencil->get(cid, vert) += 1.0f;
- stencil->get(cid, edge->to()) += 1.0f;
- stencil->get(cid, edge->next->to()) += 1.0f;
- }
- else
- stencil->get(cid, edge->next->to()) = 3.0f;
- }
-
- /* normalize stencil. */
- stencil->get(cid).normalize();
- }
- }
-}
-
-void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12};
- const int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- const int edge2Indices[7] = {12, 10, 15, 17, 14, 8, 11};
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- float tangentScales[14] = {
- 0.0f, 0.0f, 0.0f, 0.667791f, 1.0f,
- 1.11268f, 1.1284f, 1.10289f, 1.06062f,
- 1.01262f, 0.963949f, 0.916926f, 0.872541f, 0.831134f
- };
-
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* compute corner / edge control points */
- int v = 0;
-
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdVert *vert = it.current()->from();
- int valence = vert->valence();
- int cid = cornerIndices[primitiveOffset+v];
-
- int i1 = 0, i2 = 0, j = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
-
- /* find index of "our" edge for edge control points */
- if(edge == it.current())
- i1 = j;
- if(edge == it.current()->prev->pair)
- i2 = j;
- }
-
- if(vert->is_boundary()) {
- int num_verts = ring->num_verts();
- StencilMask r0(num_verts);
- StencilMask r1(num_verts);
-
- computeBoundaryTangentStencils(ring, vert, r0, r1);
-
- int k = valence - 1;
- float omega = M_PI_F / k;
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- if(it.current()->is_boundary()) {
- assert(it.current()->from() == vert);
-
- stencil->get(eid1, vert) = 2.0f / 3.0f;
- stencil->get(eid1, it.current()->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid1).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid1) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current())
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid1)[i] += (r0[i] * s + r1[i] * c) / 3.0f;
- }
-
- if(it.current()->prev->is_boundary()) {
- assert(it.current()->prev->pair->from() == vert);
-
- stencil->get(eid2, vert) = 2.0f / 3.0f;
- stencil->get(eid2, it.current()->prev->pair->to()) = 1.0f / 3.0f;
-
- assert(stencil->get(eid2).is_normalized());
-
- if(valence == 2) {
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += r0[i] * 0.0001f;
- }
- }
- else {
- stencil->get(eid2) = stencil->get(cid);
-
- /* compute index of it.current() around vert */
- int idx = 0;
-
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++)
- if(eit.current() == it.current()->prev->pair)
- break;
-
- assert(idx != valence);
-
- float c = cosf(idx * omega);
- float s = sinf(idx * omega);
-
- for(int i = 0; i < num_verts; i++)
- stencil->get(eid2)[i] += (r0[i] * s + r1[i] * c) / 3;
- }
- }
- else {
- float costerm = cosf(M_PI_F / valence);
- float sqrtterm = sqrtf(4.0f + costerm*costerm);
-
- /* float tangentScale = 1.0f; */
- float tangentScale = tangentScales[min(valence, 13U)];
-
- float alpha = (1.0f + costerm / sqrtterm) / (3.0f * valence) * tangentScale;
- float beta = 1.0f / (3.0f * valence * sqrtterm) * tangentScale;
-
-
- int eid1 = edge1Indices[primitiveOffset + v];
- int eid2 = edge2Indices[primitiveOffset + v];
-
- stencil->get(eid1) = stencil->get(cid);
- stencil->get(eid2) = stencil->get(cid);
-
- j = 0;
- for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) {
- SubdEdge *edge = eit.current();
- assert(vert->co == edge->from()->co);
-
- float costerm1_a = cosf(M_PI_F * 2 * (j-i1) / valence);
- float costerm1_b = cosf(M_PI_F * (2 * (j-i1)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
- float costerm2_a = cosf(M_PI_F * 2 * (j-i2) / valence);
- float costerm2_b = cosf(M_PI_F * (2 * (j-i2)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */
-
-
- stencil->get(eid1, edge->to()) += alpha * costerm1_a;
- stencil->get(eid2, edge->to()) += alpha * costerm2_a;
-
- if(SubdFaceRing::is_triangle(edge->face)) {
- /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */
-
- /* distribute weight to all verts */
- stencil->get(eid1, vert) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f;
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f;
-
- stencil->get(eid2, vert) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->to()) += beta * costerm2_b / 3.0f;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b / 3.0f;
- }
- else {
- stencil->get(eid1, edge->next->to()) += beta * costerm1_b;
- stencil->get(eid2, edge->next->to()) += beta * costerm2_b;
- }
- }
- }
- }
-}
-
-void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil)
-{
- static int corner1Indices[7] = {8, 11, 19, 16, 6, 9, 12};
- static int corner2Indices[7] = {11, 19, 16, 8, 9, 12, 6};
- static int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13};
- static int edge2Indices[7] = {10, 15, 17, 12, 8, 11, 14};
- static int interior1Indices[7] = {1, 3, 6, 4, 1, 3, 5};
- static int interior2Indices[7] = {2, 7, 5, 0, 2, 4, 0};
-
- int primitiveOffset = ring->is_quad()? 0: 4;
-
- SubdFace * face = ring->face();
- SubdEdge *firstEdge = ring->firstEdge();
-
- /* interior control points */
- int v = 0;
- for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) {
- SubdEdge *edge = it.current();
-
- if(edge->is_boundary()) {
- float valence1 = pseudoValence(edge->from());
- float valence2 = pseudoValence(edge->to());
-
- float weights1[4];
- float weights2[4];
-
- if(ring->is_quad()) {
- weights1[0] = 3 * valence1;
- weights1[1] = 6;
- weights1[2] = 3;
- weights1[3] = 6;
-
- weights2[0] = 6;
- weights2[1] = 3 * valence2;
- weights2[2] = 6;
- weights2[3] = 3;
- }
- else {
- assert(ring->is_triangle());
- weights1[0] = 3 * valence1 + 1;
- weights1[1] = 7;
- weights1[2] = 7;
-
- weights2[0] = 7;
- weights2[1] = 3 * valence2 + 1;
- weights2[2] = 7;
- }
-
- int idx1 = interior1Indices[primitiveOffset+v];
- int idx2 = interior2Indices[primitiveOffset+v];
-
- int i = 0;
- for(SubdFace::EdgeIterator it_sub(face->edges(edge)); !it_sub.isDone(); it_sub.advance(), i++) {
- SubdVert *vert = it_sub.current()->from();
- stencil->get(idx1, vert) += weights1[i];
- stencil->get(idx2, vert) += weights2[i];
- }
-
- stencil->get(idx1).normalize();
- stencil->get(idx2).normalize();
- }
- else {
- SubdVert *e0 = edge->from();
- float costerm0 = cosf(M_2PI_F / pseudoValence(e0));
-
- SubdVert *f0 = edge->to();
- float costerm1 = cosf(M_2PI_F / pseudoValence(f0));
-
- /* p0 +------+ q0
- * | |
- * f0 +======+ e0 <=== current edge
- * | |
- * p1 +------+ q1
- */
-
- SubdVert *q0 = edge->next->to();
- SubdVert *p0 = edge->prev->from();
-
- SubdVert *p1 = edge->pair->next->to();
- SubdVert *q1 = edge->pair->prev->from();
-
-
- StencilMask x(ring->num_verts());
- StencilMask y(ring->num_verts());
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm1 * stencil->get(corner1Indices[primitiveOffset+v])[i] -
- (2*costerm0 + costerm1) * stencil->get(edge1Indices[primitiveOffset+v])[i] +
- 2*costerm0 * stencil->get(edge2Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA1 - midedgeB1) + 4*(centroidA - centroidB))/18.0f; */
- y[ring->vert_index(p0)] = 1;
- y[ring->vert_index(p1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) {
- y *= 4.0f / 3.0f;
- }
-#endif
-
- stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]);
- stencil->get(interior1Indices[primitiveOffset+v]) += x;
- stencil->get(interior1Indices[primitiveOffset+v]) += y;
-
- for(int i = 0; i < ring->num_verts(); i++) {
- x[i] =
- (costerm0 * stencil->get(corner2Indices[primitiveOffset+v])[i] -
- (2*costerm1 + costerm0) * stencil->get(edge2Indices[primitiveOffset+v])[i] +
- 2*costerm1 * stencil->get(edge1Indices[primitiveOffset+v])[i]) / 3.0f;
- }
-
- /* y = (2*( midedgeA2 - midedgeB2) + 4*(centroidA - centroidB))/18.0f; */
- y = 0.0f;
-
- /* (2*( midedgeA2 - midedgeB2) */
- y[ring->vert_index(q0)] = 1;
- y[ring->vert_index(q1)] = -1;
-
- /* add centroidA */
- if(ring->is_triangle()) {
- y[ring->vert_index(p0)] += 4.0f / 3.0f;
- y[ring->vert_index(e0)] += 4.0f / 3.0f;
- y[ring->vert_index(f0)] += 4.0f / 3.0f;
- }
- else {
- y[ring->vert_index(p0)] += 1;
- y[ring->vert_index(q0)] += 1;
- y[ring->vert_index(e0)] += 1;
- y[ring->vert_index(f0)] += 1;
- }
-
- /* sub centroidB */
- if(SubdFaceRing::is_triangle(edge->pair->face)) {
- y[ring->vert_index(p1)] -= 4.0f / 3.0f;
- y[ring->vert_index(e0)] -= 4.0f / 3.0f;
- y[ring->vert_index(f0)] -= 4.0f / 3.0f;
-
- }
- else {
- y[ring->vert_index(p1)] -= 1;
- y[ring->vert_index(q1)] -= 1;
- y[ring->vert_index(e0)] -= 1;
- y[ring->vert_index(f0)] -= 1;
- }
-
- y /= 18.0f;
-
- if(ring->is_triangle()) {
- x *= 3.0f / 4.0f;
- y *= 3.0f / 4.0f;
- }
-
- /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */
-#if 0
- if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face))
- y *= 4.0f / 3.0f;
-#endif
-
- stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]);
- stencil->get(interior2Indices[primitiveOffset+v]) += x;
- stencil->get(interior2Indices[primitiveOffset+v]) += y;
- }
- }
-}
-
-void SubdAccBuilder::computeBoundaryTangentStencils(SubdFaceRing *ring, SubdVert *vert, StencilMask & r0, StencilMask & r1)
-{
- assert(vert->is_boundary());
- assert(r0.size() == ring->num_verts());
- assert(r1.size() == ring->num_verts());
-
- SubdEdge *edge0 = vert->edge;
- assert(edge0->face == NULL);
- assert(edge0->to() != vert);
-
- SubdEdge *edgek = vert->edge->prev;
- assert(edgek->face == NULL);
- assert(edgek->from() != vert);
-
- int valence = vert->valence();
-
- int k = valence - 1;
- float omega = M_PI_F / k;
- float s = sinf(omega);
- float c = cosf(omega);
-
- float factor = 1.0f / (3 * k + c);
-
- float gamma = -4 * s * factor;
- r0[ring->vert_index(vert)] = gamma;
- /* r1[ring->vert_index(vert)] = 0; */
-
- float salpha0 = -((1 + 2 * c) * sqrtf(1 + c)) * factor / sqrtf(1 - c);
- float calpha0 = 1.0f / 2.0f;
-
- r0[ring->vert_index(edge0->to())] = salpha0;
- r1[ring->vert_index(edge0->to())] = calpha0;
-
- float salphak = salpha0;
- float calphak = -1.0f / 2.0f;
-
- r0[ring->vert_index(edgek->from())] = salphak;
- r1[ring->vert_index(edgek->from())] = calphak;
-
- int j = 0;
- for(SubdVert::EdgeIterator it(vert->edges()); !it.isDone(); it.advance(), j++) {
- SubdEdge *edge = it.current();
-
- if(j == k) break;
-
- SubdVert *p = edge->to();
- SubdVert *q = edge->pair->prev->from();
-
- float alphaj = 4 * sinf(j * omega) * factor;
- float betaj = (sinf(j * omega) + sinf((j + 1) * omega)) * factor;
-
- if(j != 0)
- r0[ring->vert_index(p)] += alphaj;
-
- if(edge->pair->prev->prev->prev == edge->pair) {
- r0[ring->vert_index(vert)] += betaj / 3.0f;
- r0[ring->vert_index(edge->pair->from())] += betaj / 3.0f;
- r0[ring->vert_index(q)] += betaj / 3.0f;
- }
- else
- r0[ring->vert_index(q)] += betaj;
- }
-
- if(valence == 2) {
- /* r0 perpendicular to r1 */
- r0[ring->vert_index(vert)] = -4.0f / 3.0f;
- r0[ring->vert_index(edgek->from())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->to())] = 1.0f / 2.0f;
- r0[ring->vert_index(edge0->next->to())] = 1.0f / 3.0f;
- }
-}
-
-/* Subd Linear Builder */
-
-SubdLinearBuilder::SubdLinearBuilder()
-{
-}
-
-SubdLinearBuilder::~SubdLinearBuilder()
-{
-}
-
-Patch *SubdLinearBuilder::run(SubdFace *face)
-{
- Patch *patch;
- float3 *hull;
-
- if(face->num_edges() == 3) {
- LinearTrianglePatch *lpatch = new LinearTrianglePatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else if(face->num_edges() == 4) {
- LinearQuadPatch *lpatch = new LinearQuadPatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else {
- assert(0); /* n-gons should have been split already */
- return NULL;
- }
-
- int i = 0;
-
- for(SubdFace::EdgeIterator it(face->edge); !it.isDone(); it.advance())
- hull[i++] = it.current()->from()->co;
-
- if(face->num_edges() == 4)
- swap(hull[2], hull[3]);
-
- return patch;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_build.h b/intern/cycles/subd/subd_build.h
deleted file mode 100644
index 8353fb5993a..00000000000
--- a/intern/cycles/subd/subd_build.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-#ifndef __SUBD_BUILD_H__
-#define __SUBD_BUILD_H__
-
-CCL_NAMESPACE_BEGIN
-
-class SubdFace;
-class SubdFaceRing;
-class SubdVert;
-class GregoryAccStencil;
-class Patch;
-class StencilMask;
-
-/* Builder */
-
-class SubdBuilder
-{
-public:
- virtual ~SubdBuilder() {};
- virtual Patch *run(SubdFace *face) = 0;
- static SubdBuilder *create(bool linear);
-};
-
-/* Approximate Catmull Clark using Loop's approximation */
-
-class SubdAccBuilder : public SubdBuilder
-{
-public:
- SubdAccBuilder();
- ~SubdAccBuilder();
-
- Patch *run(SubdFace *face);
-
-protected:
- /* Gregory Patch */
- void computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil);
- void computeBoundaryTangentStencils(SubdFaceRing *ring,
- SubdVert *vert,
- StencilMask & r0, StencilMask & r1);
-};
-
-/* Linear Subdivision */
-
-class SubdLinearBuilder : public SubdBuilder
-{
-public:
- SubdLinearBuilder();
- ~SubdLinearBuilder();
-
- Patch *run(SubdFace *face);
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_BUILD_H__ */
-
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a42a2fc833b..05ff5ca4b65 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -26,22 +26,25 @@ CCL_NAMESPACE_BEGIN
/* EdgeDice Base */
-EdgeDice::EdgeDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
+EdgeDice::EdgeDice(const SubdParams& params_)
+: params(params_)
{
- mesh = mesh_;
mesh_P = NULL;
mesh_N = NULL;
vert_offset = 0;
- dicing_rate = dicing_rate_;
- shader = shader_;
- smooth = smooth_;
- camera = NULL;
- mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+
+ if(params.ptex) {
+ params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ }
}
void EdgeDice::reserve(int num_verts, int num_tris)
{
+ Mesh *mesh = params.mesh;
+
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
@@ -60,20 +63,38 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
patch->eval(&P, &dPdu, &dPdv, uv.x, uv.y);
N = normalize(cross(dPdu, dPdv));
- assert(vert_offset < mesh->verts.size());
+ assert(vert_offset < params.mesh->verts.size());
mesh_P[vert_offset] = P;
mesh_N[vert_offset] = N;
+ if(params.ptex) {
+ Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.reserve();
+
+ float3 *ptex_uv = attr_ptex_uv->data_float3();
+ ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
+ }
+
return vert_offset++;
}
-void EdgeDice::add_triangle(int v0, int v1, int v2)
+void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- mesh->add_triangle(v0, v1, v2, shader, smooth);
+ params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth);
+
+ if(params.ptex) {
+ Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ params.mesh->attributes.reserve();
+
+ float *ptex_face_id = attr_ptex_face_id->data_float();
+ ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
+ }
+
+ tri_offset++;
}
-void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
+void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner)
{
if(inner.size() == 0 || outer.size() == 0)
return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
@@ -106,14 +127,14 @@ void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
v2 = inner[++i];
}
- add_triangle(v0, v1, v2);
+ add_triangle(patch, v0, v1, v2);
}
}
/* QuadDice */
-QuadDice::QuadDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+QuadDice::QuadDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -121,7 +142,8 @@ void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv)
{
/* XXX need to make this also work for edge factor 0 and 1 */
int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1);
- EdgeDice::reserve(num_verts, 0);
+ int num_tris = 0;
+ EdgeDice::reserve(num_verts, num_tris);
}
float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
@@ -138,8 +160,8 @@ float3 QuadDice::eval_projected(SubPatch& sub, float u, float v)
float3 P;
sub.patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -222,7 +244,7 @@ float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv)
float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f;
/* solve for scaling factor */
- float Atri = dicing_rate*dicing_rate*0.5f;
+ float Atri = params.dicing_rate*params.dicing_rate*0.5f;
float Ntris = Apatch/Atri;
// XXX does the -sqrt solution matter
@@ -270,8 +292,8 @@ void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
int i3 = offset + 4 + i + j*(Mu-1);
int i4 = offset + 4 + (i-1) + j*(Mu-1);
- add_triangle(i1, i2, i3);
- add_triangle(i1, i3, i4);
+ add_triangle(sub.patch, i1, i2, i3);
+ add_triangle(sub.patch, i1, i3, i4);
}
}
}
@@ -288,7 +310,7 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1?
/* reserve space for new verts */
- int offset = mesh->verts.size();
+ int offset = params.mesh->verts.size();
reserve(ef, Mu, Mv);
/* corners and inner grid */
@@ -299,27 +321,27 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
vector<int> outer, inner;
add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
/* top side */
add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* left side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
- stitch_triangles(inner, outer);
+ stitch_triangles(sub.patch, inner, outer);
/* right side */
add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
- stitch_triangles(outer, inner);
+ stitch_triangles(sub.patch, outer, inner);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
/* TriangleDice */
-TriangleDice::TriangleDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_)
-: EdgeDice(mesh_, shader_, smooth_, dicing_rate_)
+TriangleDice::TriangleDice(const SubdParams& params_)
+: EdgeDice(params_)
{
}
@@ -417,9 +439,9 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
inner_w.push_back(corner_v);
/* stitch together inner/outer with triangles */
- stitch_triangles(outer_u, inner_u);
- stitch_triangles(outer_v, inner_v);
- stitch_triangles(outer_w, inner_w);
+ stitch_triangles(sub.patch, outer_u, inner_u);
+ stitch_triangles(sub.patch, outer_v, inner_v);
+ stitch_triangles(sub.patch, outer_w, inner_w);
outer_u = inner_u;
outer_v = inner_v;
@@ -429,18 +451,18 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
/* fill up last part */
if(m == -1) {
/* single triangle */
- add_triangle(outer_w[0], outer_u[0], outer_v[0]);
+ add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]);
}
else {
/* center vertex + 6 triangles */
int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));
- add_triangle(outer_w[0], outer_w[1], center);
- add_triangle(outer_w[1], outer_w[2], center);
- add_triangle(outer_u[0], outer_u[1], center);
- add_triangle(outer_u[1], outer_u[2], center);
- add_triangle(outer_v[0], outer_v[1], center);
- add_triangle(outer_v[1], outer_v[2], center);
+ add_triangle(sub.patch, outer_w[0], outer_w[1], center);
+ add_triangle(sub.patch, outer_w[1], outer_w[2], center);
+ add_triangle(sub.patch, outer_u[0], outer_u[1], center);
+ add_triangle(sub.patch, outer_u[1], outer_u[2], center);
+ add_triangle(sub.patch, outer_v[0], outer_v[1], center);
+ add_triangle(sub.patch, outer_v[1], outer_v[2], center);
}
}
@@ -452,7 +474,7 @@ void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef)
reserve(ef, M);
add_grid(sub, ef, M);
- assert(vert_offset == mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 250de59c6c3..9cf5b0d50b8 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -31,28 +31,50 @@ class Camera;
class Mesh;
class Patch;
+struct SubdParams {
+ Mesh *mesh;
+ int shader;
+ bool smooth;
+ bool ptex;
+
+ int test_steps;
+ int split_threshold;
+ float dicing_rate;
+ Camera *camera;
+
+ SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true, bool ptex_ = false)
+ {
+ mesh = mesh_;
+ shader = shader_;
+ smooth = smooth_;
+ ptex = ptex_;
+
+ test_steps = 3;
+ split_threshold = 1;
+ dicing_rate = 0.1f;
+ camera = NULL;
+ }
+
+};
+
/* EdgeDice Base */
class EdgeDice {
public:
- Camera *camera;
- Mesh *mesh;
+ SubdParams params;
float3 *mesh_P;
float3 *mesh_N;
- float dicing_rate;
size_t vert_offset;
size_t tri_offset;
- int shader;
- bool smooth;
- EdgeDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ EdgeDice(const SubdParams& params);
void reserve(int num_verts, int num_tris);
int add_vert(Patch *patch, float2 uv);
- void add_triangle(int v0, int v1, int v2);
+ void add_triangle(Patch *patch, int v0, int v1, int v2);
- void stitch_triangles(vector<int>& outer, vector<int>& inner);
+ void stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner);
};
/* Quad EdgeDice
@@ -86,7 +108,7 @@ public:
int tv1;
};
- QuadDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ QuadDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int Mu, int Mv);
float3 eval_projected(SubPatch& sub, float u, float v);
@@ -140,7 +162,7 @@ public:
int tw;
};
- TriangleDice(Mesh *mesh, int shader, bool smooth, float dicing_rate);
+ TriangleDice(const SubdParams& params);
void reserve(EdgeFactors& ef, int M);
diff --git a/intern/cycles/subd/subd_edge.h b/intern/cycles/subd/subd_edge.h
deleted file mode 100644
index edf98c8a5a0..00000000000
--- a/intern/cycles/subd/subd_edge.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * 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.
- *
- * 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
- * HOLDER 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.
- */
-
-#ifndef __SUBD_EDGE_H__
-#define __SUBD_EDGE_H__
-
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Half Edge */
-
-class SubdEdge
-{
-public:
- int id;
-
- SubdEdge *next;
- SubdEdge *prev;
- SubdEdge *pair;
- SubdVert *vert;
- SubdFace *face;
-
- SubdEdge(int id_)
- {
- id = id_;
- next = NULL;
- prev = NULL;
- pair = NULL;
- vert = NULL;
- face = NULL;
- }
-
- /* vertex queries */
- SubdVert *from() { return vert; }
- SubdVert *to() { return next->vert; }
-
- /* face queries */
- bool is_boundary() { return !(face && pair->face); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_EDGE_H__ */
-
diff --git a/intern/cycles/subd/subd_face.h b/intern/cycles/subd/subd_face.h
deleted file mode 100644
index 8f8a9ec3f47..00000000000
--- a/intern/cycles/subd/subd_face.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * 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.
- *
- * 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
- * HOLDER 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.
- */
-
-#ifndef __SUBD_FACE_H__
-#define __SUBD_FACE_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Face */
-
-class SubdFace
-{
-public:
- int id;
- SubdEdge *edge;
-
- SubdFace(int id_)
- {
- id = id_;
- edge = NULL;
- }
-
- bool contains(SubdEdge *e)
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- if(it.current() == e)
- return true;
-
- return false;
- }
-
- int num_edges()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- bool is_boundary()
- {
- for(EdgeIterator it(edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->pair->face == NULL)
- return true;
- }
-
- return false;
- }
-
- /* iterate over edges in clockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if (end == NULL) end = cur;
- cur = cur->next;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_H__ */
-
diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp
index becd5b9b5ec..0db20656f39 100644
--- a/intern/cycles/subd/subd_mesh.cpp
+++ b/intern/cycles/subd/subd_mesh.cpp
@@ -28,282 +28,391 @@
#include <stdio.h>
-#include "subd_build.h"
-#include "subd_edge.h"
-#include "subd_face.h"
#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"
-#include "subd_vert.h"
#include "util_debug.h"
#include "util_foreach.h"
+#ifdef WITH_OPENSUBDIV
+
+#include <osd/vertex.h>
+#include <osd/mesh.h>
+#include <osd/cpuComputeController.h>
+#include <osd/cpuVertexBuffer.h>
+#include <osd/cpuEvalLimitController.h>
+#include <osd/evalLimitContext.h>
+
CCL_NAMESPACE_BEGIN
-SubdMesh::SubdMesh()
+/* typedefs */
+typedef OpenSubdiv::OsdVertex OsdVertex;
+typedef OpenSubdiv::FarMesh<OsdVertex> OsdFarMesh;
+typedef OpenSubdiv::FarMeshFactory<OsdVertex> OsdFarMeshFactory;
+typedef OpenSubdiv::HbrCatmarkSubdivision<OsdVertex> OsdHbrCatmarkSubdivision;
+typedef OpenSubdiv::HbrFace<OsdVertex> OsdHbrFace;
+typedef OpenSubdiv::HbrHalfedge<OsdVertex> OsdHbrHalfEdge;
+typedef OpenSubdiv::HbrMesh<OsdVertex> OsdHbrMesh;
+typedef OpenSubdiv::HbrVertex<OsdVertex> OsdHbrVertex;
+typedef OpenSubdiv::OsdCpuComputeContext OsdCpuComputeContext;
+typedef OpenSubdiv::OsdCpuComputeController OsdCpuComputeController;
+typedef OpenSubdiv::OsdCpuEvalLimitContext OsdCpuEvalLimitContext;
+typedef OpenSubdiv::OsdCpuEvalLimitController OsdCpuEvalLimitController;
+typedef OpenSubdiv::OsdCpuVertexBuffer OsdCpuVertexBuffer;
+typedef OpenSubdiv::OsdEvalCoords OsdEvalCoords;
+typedef OpenSubdiv::OsdVertexBufferDescriptor OsdVertexBufferDescriptor;
+
+/* OpenSubdiv Patch */
+
+class OpenSubdPatch : public Patch {
+public:
+ int face_id;
+
+ OpenSubdPatch(OsdFarMesh *farmesh, OsdCpuVertexBuffer *vbuf_base)
+ {
+ face_id = 0;
+
+ /* create buffers for evaluation */
+ vbuf_P = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdu = OsdCpuVertexBuffer::Create(3, 1);
+ vbuf_dPdv = OsdCpuVertexBuffer::Create(3, 1);
+
+ P = vbuf_P->BindCpuBuffer();
+ dPdu = vbuf_dPdu->BindCpuBuffer();
+ dPdv = vbuf_dPdv->BindCpuBuffer();
+
+ /* setup evaluation context */
+ OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 3, 3); /* offset, length, stride */
+
+ evalctx = OsdCpuEvalLimitContext::Create(farmesh, false);
+ evalctx->GetVertexData().Bind(in_desc, vbuf_base, out_desc, vbuf_P, vbuf_dPdu, vbuf_dPdv);
+ }
+
+ ~OpenSubdPatch()
+ {
+ evalctx->GetVertexData().Unbind();
+
+ delete evalctx;
+ delete vbuf_P;
+ delete vbuf_dPdu;
+ delete vbuf_dPdv;
+ }
+
+ void eval(float3 *P_, float3 *dPdu_, float3 *dPdv_, float u, float v)
+ {
+ OsdEvalCoords coords;
+ coords.u = u;
+ coords.v = v;
+ coords.face = face_id;
+
+ evalctrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(coords, evalctx, 0);
+
+ *P_ = make_float3(P[0], P[1], P[2]);
+ if (dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]);
+ if (dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]);
+
+ /* optimize: skip evaluating derivatives when not needed */
+ /* todo: swapped derivatives, different winding convention? */
+ }
+
+ BoundBox bound()
+ {
+ /* not implemented */
+ BoundBox bbox = BoundBox::empty;
+ return bbox;
+ }
+
+ int ptex_face_id()
+ {
+ return face_id;
+ }
+
+protected:
+ OsdCpuEvalLimitController evalctrl;
+ OsdCpuEvalLimitContext *evalctx;
+ OsdCpuVertexBuffer *vbuf_P;
+ OsdCpuVertexBuffer *vbuf_dPdu;
+ OsdCpuVertexBuffer *vbuf_dPdv;
+ float *P;
+ float *dPdu;
+ float *dPdv;
+};
+
+/* OpenSubdiv Mesh */
+
+OpenSubdMesh::OpenSubdMesh()
{
+ /* create osd mesh */
+ static OsdHbrCatmarkSubdivision catmark;
+ OsdHbrMesh *hbrmesh = new OsdHbrMesh(&catmark);
+
+ /* initialize class */
+ num_verts = 0;
+ num_ptex_faces = 0;
+ _hbrmesh = (void*)hbrmesh;
}
-SubdMesh::~SubdMesh()
+OpenSubdMesh::~OpenSubdMesh()
{
- pair<Key, SubdEdge*> em;
-
- foreach(SubdVert *vertex, verts)
- delete vertex;
- foreach(em, edge_map)
- delete em.second;
- foreach(SubdFace *face, faces)
- delete face;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- verts.clear();
- edges.clear();
- edge_map.clear();
- faces.clear();
+ if(hbrmesh)
+ delete hbrmesh;
}
-SubdVert *SubdMesh::add_vert(const float3& co)
+void OpenSubdMesh::add_vert(const float3& co)
{
- SubdVert *v = new SubdVert(verts.size());
- v->co = co;
- verts.push_back(v);
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- return v;
+ OsdVertex v;
+ positions.push_back(co.x);
+ positions.push_back(co.y);
+ positions.push_back(co.z);
+ hbrmesh->NewVertex(num_verts++, v);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+void OpenSubdMesh::add_face(int v0, int v1, int v2)
{
int index[3] = {v0, v1, v2};
return add_face(index, 3);
}
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3)
{
int index[4] = {v0, v1, v2, v3};
- return add_face(index, 4);
+ add_face(index, 4);
}
-SubdFace *SubdMesh::add_face(int *index, int num)
+void OpenSubdMesh::add_face(int *index, int num)
{
- /* test non-manifold cases */
- if(!can_add_face(index, num)) {
- /* we could try to add face in opposite winding instead .. */
- fprintf(stderr, "Warning: non manifold mesh, invalid face '%lu'.\n", (unsigned long)faces.size());
- return NULL;
- }
-
- SubdFace *f = new SubdFace(faces.size());
-
- SubdEdge *first_edge = NULL;
- SubdEdge *last = NULL;
- SubdEdge *current = NULL;
-
- /* add edges */
- for(int i = 0; i < num-1; i++) {
- current = add_edge(index[i], index[i+1]);
- assert(current != NULL);
-
- current->face = f;
-
- if(last != NULL) {
- last->next = current;
- current->prev = last;
- }
- else
- first_edge = current;
-
- last = current;
- }
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- current = add_edge(index[num-1], index[0]);
- assert(current != NULL);
-
- current->face = f;
+#ifndef NDEBUG
+ /* sanity checks */
+ for(int j = 0; j < num; j++) {
+ OsdHbrVertex *origin = hbrmesh->GetVertex(index[j]);
+ OsdHbrVertex *destination = hbrmesh->GetVertex(index[(j+1)%num]);
+ OsdHbrHalfEdge *opposite = destination->GetEdge(origin);
- last->next = current;
- current->prev = last;
+ if(origin==NULL || destination==NULL)
+ assert("An edge was specified that connected a nonexistent vertex\n");
- current->next = first_edge;
- first_edge->prev = current;
+ if(origin == destination)
+ assert("An edge was specified that connected a vertex to itself\n");
- f->edge = first_edge;
- faces.push_back(f);
+ if(opposite && opposite->GetOpposite())
+ assert("A non-manifold edge incident to more than 2 faces was found\n");
- return f;
-}
+ if(origin->GetEdge(destination))
+ assert("An edge connecting two vertices was specified more than once."
+ "It's likely that an incident face was flipped\n");
+ }
+#endif
-bool SubdMesh::can_add_face(int *index, int num)
-{
- /* manifold check */
- for(int i = 0; i < num-1; i++)
- if(!can_add_edge(index[i], index[i+1]))
- return false;
+ OsdHbrFace *face = hbrmesh->NewFace(num, index, 0);
+
+ /* this is required for limit eval patch table? */
+ face->SetPtexIndex(num_ptex_faces);
- return can_add_edge(index[num-1], index[0]);
+ if(num == 4)
+ num_ptex_faces++;
+ else
+ num_ptex_faces += num;
}
-bool SubdMesh::can_add_edge(int i, int j)
+bool OpenSubdMesh::finish()
{
- /* check for degenerate edge */
- if(i == j)
- return false;
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- /* make sure edge has not been added yet. */
- return find_edge(i, j) == NULL;
-}
+ /* finish hbr mesh construction */
+ hbrmesh->SetInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
+ hbrmesh->Finish();
-SubdEdge *SubdMesh::add_edge(int i, int j)
-{
- SubdEdge *edge;
-
- /* find pair */
- SubdEdge *pair = find_edge(j, i);
-
- if(pair != NULL) {
- /* create edge with same id */
- edge = new SubdEdge(pair->id + 1);
-
- /* link edge pairs */
- edge->pair = pair;
- pair->pair = edge;
-
- /* not sure this is necessary? */
- pair->vert->edge = pair;
- }
- else {
- /* create edge */
- edge = new SubdEdge(2*edges.size());
-
- /* add only unpaired edges */
- edges.push_back(edge);
- }
-
- /* assign vertex and put into map */
- edge->vert = verts[i];
- edge_map[Key(i, j)] = edge;
-
- /* face and next are set by add_face */
-
- return edge;
+ return true;
}
-SubdEdge *SubdMesh::find_edge(int i, int j)
+void OpenSubdMesh::tessellate(DiagSplit *split)
{
- map<Key, SubdEdge*>::const_iterator it = edge_map.find(Key(i, j));
+ if (num_ptex_faces == 0)
+ return;
- return (it == edge_map.end())? NULL: it->second;
-}
+ const int level = 3;
+ const bool requirefvar = false;
-bool SubdMesh::link_boundary()
-{
- /* link boundary edges once the mesh has been created */
- int num = 0;
-
- /* create boundary edges */
- int num_edges = edges.size();
+ /* convert HRB to FAR mesh */
+ OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ OsdFarMeshFactory meshFactory(hbrmesh, level, true);
+ OsdFarMesh *farmesh = meshFactory.Create(requirefvar);
+ int num_hbr_verts = hbrmesh->GetNumVertices();
- if(edge->pair == NULL) {
- SubdEdge *pair = new SubdEdge(edge->id + 1);
+ delete hbrmesh;
+ hbrmesh = NULL;
+ _hbrmesh = NULL;
- int i = edge->from()->id;
- int j = edge->to()->id;
+ /* refine HBR mesh with vertex coordinates */
+ OsdCpuComputeController *compute_controller = new OsdCpuComputeController();
+ OsdCpuComputeContext *compute_context = OsdCpuComputeContext::Create(farmesh);
- assert(edge_map.find(Key(j, i)) == edge_map.end());
+ OsdCpuVertexBuffer *vbuf_base = OsdCpuVertexBuffer::Create(3, num_hbr_verts);
+ vbuf_base->UpdateData(&positions[0], 0, num_verts);
- pair->vert = verts[j];
- edge_map[Key(j, i)] = pair;
-
- edge->pair = pair;
- pair->pair = edge;
-
- num++;
- }
- }
+ compute_controller->Refine(compute_context, farmesh->GetKernelBatches(), vbuf_base);
+ compute_controller->Synchronize();
- /* link boundary edges */
- for(int e = 0; e < num_edges; e++) {
- SubdEdge *edge = edges[e];
+ /* split & dice patches */
+ OpenSubdPatch patch(farmesh, vbuf_base);
- if(edge->pair->face == NULL)
- link_boundary_edge(edge->pair);
+ for(int f = 0; f < num_ptex_faces; f++) {
+ patch.face_id = f;
+ split->split_quad(&patch);
}
-
- /* detect boundary intersections */
- int boundaryIntersections = 0;
- int num_verts = verts.size();
- for(int v = 0; v < num_verts; v++) {
- SubdVert *vertex = verts[v];
+ /* clean up */
+ delete farmesh;
+ delete compute_controller;
+ delete compute_context;
+ delete vbuf_base;
+}
- int boundarySubdEdges = 0;
- for(SubdVert::EdgeIterator it(vertex->edges()); !it.isDone(); it.advance())
- if(it.current()->is_boundary())
- boundarySubdEdges++;
+CCL_NAMESPACE_END
- if(boundarySubdEdges > 2) {
- assert((boundarySubdEdges & 1) == 0);
- boundaryIntersections++;
- }
+#else /* WITH_OPENSUBDIV */
+
+CCL_NAMESPACE_BEGIN
+
+/* Subd Vertex */
+
+class SubdVert
+{
+public:
+ int id;
+ float3 co;
+
+ SubdVert(int id_)
+ {
+ id = id_;
+ co = make_float3(0.0f, 0.0f, 0.0f);
}
+};
- if(boundaryIntersections != 0) {
- fprintf(stderr, "Invalid mesh, boundary intersections found!\n");
- return false;
+/* Subd Face */
+
+class SubdFace
+{
+public:
+ int id;
+ int numverts;
+ int verts[4];
+
+ SubdFace(int id_)
+ {
+ id = id_;
+ numverts = 0;
}
+};
- return true;
+/* Subd Mesh */
+
+SubdMesh::SubdMesh()
+{
}
-void SubdMesh::link_boundary_edge(SubdEdge *edge)
+SubdMesh::~SubdMesh()
{
- /* link this boundary edge. */
+ foreach(SubdVert *vertex, verts)
+ delete vertex;
+ foreach(SubdFace *face, faces)
+ delete face;
- /* make sure next pointer has not been set. */
- assert(edge->face == NULL);
- assert(edge->next == NULL);
-
- SubdEdge *next = edge;
+ verts.clear();
+ faces.clear();
+}
- while(next->pair->face != NULL) {
- /* get pair prev */
- SubdEdge *e = next->pair->next;
+SubdVert *SubdMesh::add_vert(const float3& co)
+{
+ SubdVert *v = new SubdVert(verts.size());
+ v->co = co;
+ verts.push_back(v);
- while(e->next != next->pair)
- e = e->next;
+ return v;
+}
- next = e;
- }
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
+{
+ int index[3] = {v0, v1, v2};
+ return add_face(index, 3);
+}
- edge->next = next->pair;
- next->pair->prev = edge;
-
- /* adjust vertex edge, so that it's the boundary edge. (required for is_boundary()) */
- if(edge->vert->edge != edge)
- edge->vert->edge = edge;
+SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
+{
+ int index[4] = {v0, v1, v2, v3};
+ return add_face(index, 4);
+}
+
+SubdFace *SubdMesh::add_face(int *index, int num)
+{
+ /* skip ngons */
+ if(num < 3 || num > 4)
+ return NULL;
+
+ SubdFace *f = new SubdFace(faces.size());
+
+ for(int i = 0; i < num; i++)
+ f->verts[i] = index[i];
+
+ f->numverts = num;
+ faces.push_back(f);
+
+ return f;
+}
+
+bool SubdMesh::finish()
+{
+ return true;
}
-void SubdMesh::tessellate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
+void SubdMesh::tessellate(DiagSplit *split)
{
- SubdBuilder *builder = SubdBuilder::create(linear);
int num_faces = faces.size();
for(int f = 0; f < num_faces; f++) {
SubdFace *face = faces[f];
- Patch *patch = builder->run(face);
+ Patch *patch;
+ float3 *hull;
+
+ if(face->numverts == 3) {
+ LinearTrianglePatch *lpatch = new LinearTrianglePatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else if(face->numverts == 4) {
+ LinearQuadPatch *lpatch = new LinearQuadPatch();
+ hull = lpatch->hull;
+ patch = lpatch;
+ }
+ else {
+ assert(0); /* n-gons should have been split already */
+ continue;
+ }
+
+ for(int i = 0; i < face->numverts; i++)
+ hull[i] = verts[face->verts[i]]->co;
+
+ if(face->numverts == 4)
+ swap(hull[2], hull[3]);
if(patch->is_triangle())
- split->split_triangle(mesh, patch, shader, smooth);
+ split->split_triangle(patch);
else
- split->split_quad(mesh, patch, shader, smooth);
+ split->split_quad(patch);
delete patch;
}
-
- delete builder;
}
CCL_NAMESPACE_END
+#endif /* WITH_OPENSUBDIV */
+
diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h
index e4bd5f192ab..f6aefc20318 100644
--- a/intern/cycles/subd/subd_mesh.h
+++ b/intern/cycles/subd/subd_mesh.h
@@ -35,22 +35,19 @@
CCL_NAMESPACE_BEGIN
-class SubdFace;
+#ifndef WITH_OPENSUBDIV
class SubdVert;
-class SubdEdge;
+class SubdFace;
+#endif
class DiagSplit;
class Mesh;
-/* Subd Mesh, half edge based for dynamic mesh manipulation */
+/* Subd Mesh with simple linear subdivision */
class SubdMesh
{
public:
- vector<SubdVert*> verts;
- vector<SubdEdge*> edges;
- vector<SubdFace*> faces;
-
SubdMesh();
~SubdMesh();
@@ -60,28 +57,19 @@ public:
SubdFace *add_face(int v0, int v1, int v2, int v3);
SubdFace *add_face(int *index, int num);
- bool link_boundary();
- void tessellate(DiagSplit *split, bool linear,
- Mesh *mesh, int shader, bool smooth);
+ bool finish();
+ void tessellate(DiagSplit *split);
protected:
- bool can_add_face(int *index, int num);
- bool can_add_edge(int i, int j);
- SubdEdge *add_edge(int i, int j);
- SubdEdge *find_edge(int i, int j);
- void link_boundary_edge(SubdEdge *edge);
-
- struct Key {
- Key() {}
- Key(int v0, int v1) : p0(v0), p1(v1) {}
-
- bool operator<(const Key& k) const
- { return (p0 < k.p0 || (p0 == k.p0 && p1 < k.p1)); }
-
- int p0, p1;
- };
+#ifdef WITH_OPENSUBDIV
+ void *_hbrmesh;
+ vector<float> positions;
+ int num_verts, num_ptex_faces;
+#else
+ vector<SubdVert*> verts;
+ vector<SubdFace*> faces;
+#endif
- map<Key, SubdEdge *> edge_map;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index 4a029277370..fe9fa791813 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -27,14 +27,6 @@ CCL_NAMESPACE_BEGIN
/* De Casteljau Evaluation */
-static float3 decasteljau_quadratic(float t, const float3 cp[3])
-{
- float3 d0 = cp[0] + t*(cp[1] - cp[0]);
- float3 d1 = cp[1] + t*(cp[2] - cp[1]);
-
- return d0 + t*(d1 - d0);
-}
-
static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4])
{
float3 d0 = cp[0] + t*(cp[1] - cp[0]);
@@ -63,17 +55,6 @@ static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3
if(du) decasteljau_cubic(du, NULL, v, utn);
}
-static float3 decasteljau_tangent(const float3 cp[12], float u, float v)
-{
- float3 ucp[3];
-
- decasteljau_cubic(ucp+0, NULL, v, cp);
- decasteljau_cubic(ucp+1, NULL, v, cp+4);
- decasteljau_cubic(ucp+2, NULL, v, cp+8);
-
- return decasteljau_quadratic(u, ucp);
-}
-
/* Linear Quad Patch */
void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
@@ -138,149 +119,5 @@ BoundBox BicubicPatch::bound()
return bbox;
}
-/* Bicubic Patch with Tangent Fields */
-
-void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- decasteljau_bicubic(P, NULL, NULL, hull, u, v);
-
- if(dPdu) *dPdu = decasteljau_tangent(utan, u, v);
- if(dPdv) *dPdv = decasteljau_tangent(vtan, v, u);
-}
-
-BoundBox BicubicTangentPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 16; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-/* Gregory Patch */
-
-static float no_zero_div(float f)
-{
- if(f == 0.0f) return 1.0f;
- return f;
-}
-
-void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- float3 bicubic[16];
-
- float U = 1 - u;
- float V = 1 - v;
-
- /* 8 9 10 11
- * 12 0\1 2/3 13
- * 14 4/5 6\7 15
- * 16 17 18 19
- */
-
- bicubic[5] = (u*hull[1] + v*hull[0])/no_zero_div(u + v);
- bicubic[6] = (U*hull[2] + v*hull[3])/no_zero_div(U + v);
- bicubic[9] = (u*hull[5] + V*hull[4])/no_zero_div(u + V);
- bicubic[10] = (U*hull[6] + V*hull[7])/no_zero_div(U + V);
-
- // Map gregory control points to bezier control points.
- bicubic[0] = hull[8];
- bicubic[1] = hull[9];
- bicubic[2] = hull[10];
- bicubic[3] = hull[11];
- bicubic[4] = hull[12];
- bicubic[7] = hull[13];
- bicubic[8] = hull[14];
- bicubic[11] = hull[15];
- bicubic[12] = hull[16];
- bicubic[13] = hull[17];
- bicubic[14] = hull[18];
- bicubic[15] = hull[19];
-
- decasteljau_bicubic(P, dPdu, dPdv, bicubic, u, v);
-}
-
-BoundBox GregoryQuadPatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
-void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
-{
- /* 6
- *
- * 14 0/1 7
- *
- * 13 5/4 3\2 8
- *
- * 12 11 10 9
- */
-
- float w = 1 - u - v;
- float uu = u * u;
- float vv = v * v;
- float ww = w * w;
- float uuu = uu * u;
- float vvv = vv * v;
- float www = ww * w;
-
- float U = 1 - u;
- float V = 1 - v;
- float W = 1 - w;
-
- float3 C0 = ( v*U * hull[5] + u*V * hull[4] ) / no_zero_div(v*U + u*V);
- float3 C1 = ( w*V * hull[3] + v*W * hull[2] ) / no_zero_div(w*V + v*W);
- float3 C2 = ( u*W * hull[1] + w*U * hull[0] ) / no_zero_div(u*W + w*U);
-
- *P =
- (hull[12] * www + 3*hull[11] * ww*u + 3*hull[10] * w*uu + hull[ 9]*uuu) * (w + u) +
- (hull[ 9] * uuu + 3*hull[ 8] * uu*v + 3*hull[ 7] * u*vv + hull[ 6]*vvv) * (u + v) +
- (hull[ 6] * vvv + 3*hull[14] * vv*w + 3*hull[13] * v*ww + hull[12]*www) * (v + w) -
- (hull[12] * www*w + hull[ 9] * uuu*u + hull[ 6] * vvv*v) +
- 12*(C0 * u*v*ww + C1 * uu*v*w + C2 * u*vv*w);
-
- if(dPdu || dPdv) {
- float3 E1 = (hull[12]*www + 3*hull[11]*ww*u + 3*hull[10]*w*uu + hull[ 9]*uuu);
- float3 E2 = (hull[ 9]*uuu + 3*hull[ 8]*uu*v + 3*hull[ 7]*u*vv + hull[ 6]*vvv);
- float3 E3 = (hull[ 6]*vvv + 3*hull[14]*vv*w + 3*hull[13]*v*ww + hull[12]*www);
-
- if(dPdu) {
- float3 E1u = 3*( - hull[12]*ww + hull[11]*(ww-2*u*w) + hull[10]*(2*u*w-uu) + hull[ 9]*uu);
- float3 E2u = 3*( hull[ 9]*uu + 2*hull[ 8]*u*v + hull[ 7]*vv );
- float3 E3u = 3*( - hull[14]*vv - 2*hull[13]*v*w - hull[12]*ww);
- float3 Su = 4*( -hull[12]*www + hull[9]*uuu);
- float3 Cu = 12*( C0*(ww*v-2*u*v*w) + C1*(2*u*v*w-uu*v) + C2*vv*(w-u) );
-
- *dPdu = E1u*(w+u) + (E2+E2u*(u+v)) + (E3u*(v+w)-E3) - Su + Cu;
- }
-
- if(dPdv) {
- float3 E1v = 3*(-hull[12]*ww - 2*hull[11]*w*u - hull[10]*uu );
- float3 E2v = 3*( hull[ 8]*uu + 2*hull[ 7]*u*v + hull[ 6]*vv);
- float3 E3v = 3*( hull[ 6]*vv + hull[14]*(2*w*v-vv) + hull[13]*(ww-2*w*v) - hull[12]*ww);
- float3 Sv = 4*(-hull[12]*www + hull[ 6]*vvv);
- float3 Cv = 12*(C0*(u*ww-2*u*v*w) + C1*uu*(w-v) + C2*(2*u*v*w-u*vv));
-
- *dPdv = ((E1v*(w+u)-E1) + (E2+E2v*(u+v)) + E3v*(v+w) - Sv + Cv );
- }
- }
-}
-
-BoundBox GregoryTrianglePatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 20; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 7755740ea0c..48f35d78711 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -22,16 +22,13 @@
CCL_NAMESPACE_BEGIN
-class Mesh;
-
-/* Base */
-
class Patch {
public:
virtual ~Patch() {}
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v) = 0;
- virtual bool is_triangle() = 0;
+ virtual bool is_triangle() { return false; }
virtual BoundBox bound() = 0;
+ virtual int ptex_face_id() { return -1; }
};
/* Linear Quad Patch */
@@ -67,39 +64,6 @@ public:
BoundBox bound();
};
-/* Bicubic Patch with Tangent Fields */
-
-class BicubicTangentPatch : public Patch {
-public:
- float3 hull[16];
- float3 utan[12];
- float3 vtan[12];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-/* Gregory Patches */
-
-class GregoryQuadPatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-class GregoryTrianglePatch : public Patch {
-public:
- float3 hull[20];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v);
- bool is_triangle() { return true; }
- BoundBox bound();
-};
-
CCL_NAMESPACE_END
#endif /* __SUBD_PATCH_H__ */
diff --git a/intern/cycles/subd/subd_ring.cpp b/intern/cycles/subd/subd_ring.cpp
deleted file mode 100644
index 66eab02231c..00000000000
--- a/intern/cycles/subd/subd_ring.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "subd_face.h"
-#include "subd_ring.h"
-#include "subd_stencil.h"
-#include "subd_vert.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Utility for sorting verts by index */
-
-class vertex_compare
-{
-public:
- const vector<int>& index;
- vertex_compare(const vector<int>& index_) : index(index_) {}
- bool operator()(int a, int b) const { return index[a] < index[b]; }
-};
-
-/* Subd Face Ring */
-
-SubdFaceRing::SubdFaceRing(SubdFace *face, SubdEdge *firstEdge)
-{
- m_face = face;
- m_firstEdge = firstEdge;
- m_num_edges = face->num_edges();
-
- assert(m_num_edges == 3 || m_num_edges == 4);
-
- initVerts();
-}
-
-int SubdFaceRing::num_verts()
-{
- return m_verts.size();
-}
-
-SubdVert *SubdFaceRing::vertexAt(int i)
-{
- return m_verts[i];
-}
-
-int SubdFaceRing::vert_index(SubdVert *vertex)
-{
- int count = this->num_verts();
-
- for(int i = 0; i < count; i++)
- if(m_verts[i] == vertex)
- return i;
-
- assert(0);
- return 0;
-}
-
-void SubdFaceRing::evaluate_stencils(float3 *P, StencilMask *mask, int num)
-{
- /* first we sort verts by id. this way verts will always be added
- * in the same order to ensure the exact same float ops happen for control
- * points of other patches, so we get water-tight patches */
- int num_verts = m_verts.size();
-
- vector<int> vmap(num_verts);
- vector<int> vertid(num_verts);
-
- for(int v = 0; v < num_verts; v++) {
- vmap[v] = v;
- vertid[v] = m_verts[v]->id;
- }
-
- sort(vmap.begin(), vmap.end(), vertex_compare(vertid));
-
- /* then evaluate the stencils */
- for(int j = 0; j < num; j++) {
- float3 p = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < num_verts; i++) {
- int idx = vmap[i];
- p += m_verts[idx]->co * mask[j][idx];
- }
-
- P[j] = p;
- }
-}
-
-bool SubdFaceRing::is_triangle()
-{
- return m_num_edges == 3;
-}
-
-bool SubdFaceRing::is_quad()
-{
- return m_num_edges == 4;
-}
-
-int SubdFaceRing::num_edges()
-{
- return m_num_edges;
-}
-
-bool SubdFaceRing::is_regular(SubdFace *face)
-{
- if(!is_quad(face))
- return false;
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- /* regular faces don't have boundary edges */
- if(edge->is_boundary())
- return false;
-
- /* regular faces only have ordinary verts */
- if(edge->vert->valence() != 4)
- return false;
-
- /* regular faces are only adjacent to quads */
- for(SubdVert::EdgeIterator eit(edge); !eit.isDone(); eit.advance())
- if(eit.current()->face == NULL || eit.current()->face->num_edges() != 4)
- return false;
- }
-
- return true;
-}
-
-bool SubdFaceRing::is_triangle(SubdFace *face)
-{
- return face->num_edges() == 3;
-}
-bool SubdFaceRing::is_quad(SubdFace *face)
-{
- return face->num_edges() == 4;
-}
-
-bool SubdFaceRing::is_boundary(SubdFace *face)
-{
- /* note that face->is_boundary() returns a different result. That function
- * returns true when any of the *edges* are on the boundary. however, this
- * function returns true if any of the face *verts* are on the boundary. */
-
- for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
-
- if(edge->vert->is_boundary())
- return true;
- }
-
- return false;
-}
-
-void SubdFaceRing::initVerts()
-{
- m_verts.reserve(16);
-
- /* add face verts */
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *edge = it.current();
- m_verts.push_back(edge->from());
- }
-
- // @@ Add support for non manifold surfaces!
- // The fix:
- // - not all colocals should point to the same edge.
- // - multiple colocals could belong to different boundaries, make sure they point to the right one.
-
- // @@ When the face neighborhood wraps that could result in overlapping stencils.
-
- // Add surronding verts.
- for(SubdFace::EdgeIterator it(m_firstEdge); !it.isDone(); it.advance()) {
- SubdEdge *firstEdge = it.current();
-
- int i = 0;
-
- /* traverse edges around vertex */
- for(SubdVert::ReverseEdgeIterator eit(firstEdge); !eit.isDone(); eit.advance(), i++) {
- SubdEdge *edge = eit.current();
-
- assert(edge->from()->co == firstEdge->from()->co);
-
- add_vert(edge->to());
-
- if(edge->face != NULL)
- add_vert(edge->next->to());
- }
-
- assert(i == firstEdge->from()->valence());
- }
-}
-
-
-void SubdFaceRing::add_vert(SubdVert *vertex)
-{
- /* avoid having duplicate verts */
- if(!has_vert(vertex))
- m_verts.push_back(vertex);
-}
-
-bool SubdFaceRing::has_vert(SubdVert *vertex)
-{
- int num_verts = m_verts.size();
-
- for(int i = 0; i < num_verts; i++)
- if(m_verts[i]->co == vertex->co)
- return true;
-
- return false;
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_ring.h b/intern/cycles/subd/subd_ring.h
deleted file mode 100644
index f25342233b0..00000000000
--- a/intern/cycles/subd/subd_ring.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_FACE_RING_H__
-#define __SUBD_FACE_RING_H__
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask;
-class SubdVert;
-class SubdEdge;
-class SubdFace;
-
-class SubdFaceRing
-{
-public:
- SubdFaceRing(SubdFace *face, SubdEdge *edge);
-
- SubdFace *face() { return m_face; }
- SubdEdge *firstEdge() { return m_firstEdge; }
-
- int num_verts();
- SubdVert *vertexAt(int i);
- int vert_index(SubdVert *vertex);
-
- void evaluate_stencils(float3 *P, StencilMask *mask, int num);
-
- bool is_triangle();
- bool is_quad();
- int num_edges();
-
- static bool is_regular(SubdFace *face);
- static bool is_triangle(SubdFace *face);
- static bool is_quad(SubdFace *face);
- static bool is_boundary(SubdFace *face);
-
-protected:
- void initVerts();
- void add_vert(SubdVert *vertex);
- bool has_vert(SubdVert *vertex);
-
-protected:
- SubdFace *m_face;
- SubdEdge *m_firstEdge;
-
- int m_num_edges;
- vector<SubdVert*> m_verts;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_FACE_RING_H__ */
-
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 6c1486cecca..417ecfffd49 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -29,12 +29,9 @@ CCL_NAMESPACE_BEGIN
/* DiagSplit */
-DiagSplit::DiagSplit()
+DiagSplit::DiagSplit(const SubdParams& params_)
+: params(params_)
{
- test_steps = 3;
- split_threshold = 1;
- dicing_rate = 0.1f;
- camera = NULL;
}
void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
@@ -54,8 +51,8 @@ float3 DiagSplit::project(Patch *patch, float2 uv)
float3 P;
patch->eval(&P, NULL, NULL, uv.x, uv.y);
- if(camera)
- P = transform_perspective(&camera->worldtoraster, P);
+ if(params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
return P;
}
@@ -66,8 +63,8 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
float Lsum = 0.0f;
float Lmax = 0.0f;
- for(int i = 0; i < test_steps; i++) {
- float t = i/(float)(test_steps-1);
+ for(int i = 0; i < params.test_steps; i++) {
+ float t = i/(float)(params.test_steps-1);
float3 P = project(patch, Pstart + t*(Pend - Pstart));
@@ -80,10 +77,10 @@ int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
Plast = P;
}
- int tmin = (int)ceil(Lsum/dicing_rate);
- int tmax = (int)ceil((test_steps-1)*Lmax/dicing_rate); // XXX paper says N instead of N-1, seems wrong?
+ int tmin = (int)ceil(Lsum/params.dicing_rate);
+ int tmax = (int)ceil((params.test_steps-1)*Lmax/params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
- if(tmax - tmin > split_threshold)
+ if(tmax - tmin > params.split_threshold)
return DSPLIT_NON_UNIFORM;
return tmax;
@@ -244,7 +241,7 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
dispatch(sub, ef);
}
-void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_triangle(Patch *patch)
{
TriangleDice::SubPatch sub_split;
TriangleDice::EdgeFactors ef_split;
@@ -260,8 +257,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
split(sub_split, ef_split);
- TriangleDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ TriangleDice dice(params);
for(size_t i = 0; i < subpatches_triangle.size(); i++) {
TriangleDice::SubPatch& sub = subpatches_triangle[i];
@@ -282,7 +278,7 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth
edgefactors_triangle.clear();
}
-void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
+void DiagSplit::split_quad(Patch *patch)
{
QuadDice::SubPatch sub_split;
QuadDice::EdgeFactors ef_split;
@@ -300,8 +296,7 @@ void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth)
split(sub_split, ef_split);
- QuadDice dice(mesh, shader, smooth, dicing_rate);
- dice.camera = camera;
+ QuadDice dice(params);
for(size_t i = 0; i < subpatches_quad.size(); i++) {
QuadDice::SubPatch& sub = subpatches_quad[i];
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 9dd10f8af8f..3f9a2721977 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -41,12 +41,9 @@ public:
vector<TriangleDice::SubPatch> subpatches_triangle;
vector<TriangleDice::EdgeFactors> edgefactors_triangle;
- int test_steps;
- int split_threshold;
- float dicing_rate;
- Camera *camera;
+ SubdParams params;
- DiagSplit();
+ DiagSplit(const SubdParams& params);
float3 project(Patch *patch, float2 uv);
int T(Patch *patch, float2 Pstart, float2 Pend);
@@ -59,8 +56,8 @@ public:
void dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef);
void split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth=0);
- void split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth);
- void split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth);
+ void split_triangle(Patch *patch);
+ void split_quad(Patch *patch);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_stencil.cpp b/intern/cycles/subd/subd_stencil.cpp
deleted file mode 100644
index 5f76a942a59..00000000000
--- a/intern/cycles/subd/subd_stencil.cpp
+++ /dev/null
@@ -1,101 +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 "subd_stencil.h"
-
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-StencilMask::StencilMask()
-{
-}
-
-StencilMask::StencilMask(int size)
-{
- /* initialize weights to zero. */
- weights.resize(size, 0.0f);
-}
-
-void StencilMask::resize(int size)
-{
- weights.resize(size, 0.0f);
-}
-
-StencilMask& StencilMask::operator=(float value)
-{
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] = value;
-
- return *this;
-}
-
-void StencilMask::operator+=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] += mask.weights[i];
-}
-
-void StencilMask::operator-=(const StencilMask& mask)
-{
- assert(mask.size() == size());
-
- const int size = weights.size();
- for(int i = 0; i < size; i++)
- weights[i] -= mask.weights[i];
-}
-
-void StencilMask::operator*=(float scale)
-{
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- weights[i] *= scale;
-}
-
-void StencilMask::operator/=(float scale)
-{
- *this *= 1.0f/scale;
-}
-
-float StencilMask::sum() const
-{
- float total = 0.0f;
- const int size = weights.size();
-
- for(int i = 0; i < size; i++)
- total += weights[i];
-
- return total;
-}
-
-bool StencilMask::is_normalized() const
-{
- return fabsf(sum() - 1.0f) < 0.0001f;
-}
-
-void StencilMask::normalize()
-{
- *this /= sum();
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/subd/subd_stencil.h b/intern/cycles/subd/subd_stencil.h
deleted file mode 100644
index e11d8f37cd3..00000000000
--- a/intern/cycles/subd/subd_stencil.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com>
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef __SUBD_STENCIL__
-#define __SUBD_STENCIL__
-
-#include "util_types.h"
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-class StencilMask
-{
-public:
- StencilMask();
- StencilMask(int size);
-
- void resize(int size);
-
- StencilMask& operator=(float value);
-
- void operator+=(const StencilMask& mask);
- void operator-=(const StencilMask& mask);
- void operator*=(float scale);
- void operator/=(float scale);
-
- int size() const { return weights.size(); }
-
- float operator[](int i) const { return weights[i]; }
- float& operator[](int i) { return weights[i]; }
-
- float sum() const;
- bool is_normalized() const;
- void normalize();
-
-private:
- vector<float> weights;
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_STENCIL__ */
-
diff --git a/intern/cycles/subd/subd_vert.h b/intern/cycles/subd/subd_vert.h
deleted file mode 100644
index 638019547ae..00000000000
--- a/intern/cycles/subd/subd_vert.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * 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.
- *
- * 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
- * HOLDER 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.
- */
-
-#ifndef __SUBD_VERTEX_H__
-#define __SUBD_VERTEX_H__
-
-#include "subd_edge.h"
-#include "subd_mesh.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Vertex */
-
-class SubdVert
-{
-public:
- int id;
- float3 co;
-
- SubdEdge *edge;
- SubdVert *next;
- SubdVert *prev;
-
- SubdVert(int id_)
- {
- id = id_;
- edge = NULL;
- co = make_float3(0.0f, 0.0f, 0.0f);
-
- next = this;
- prev = this;
- }
-
- /* valence */
- int valence()
- {
- int num = 0;
-
- for(EdgeIterator it(edges()); !it.isDone(); it.advance())
- num++;
-
- return num;
- }
-
- /* edge queries */
- bool is_boundary() { return (edge && !edge->face); }
-
- /* iterator over edges in counterclockwise order */
- class EdgeIterator
- {
- public:
- EdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->pair->next;
- //cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- /* iterator over edges in clockwise order */
- class ReverseEdgeIterator
- {
- public:
- ReverseEdgeIterator(SubdEdge *e) : end(NULL), cur(e) { }
-
- virtual void advance()
- {
- if(end == NULL) end = cur;
- cur = cur->prev->pair;
- }
-
- virtual bool isDone() { return end == cur; }
- virtual SubdEdge *current() { return cur; }
-
- private:
- SubdEdge *end;
- SubdEdge *cur;
- };
-
- EdgeIterator edges() { return EdgeIterator(edge); }
- EdgeIterator edges(SubdEdge *edge) { return EdgeIterator(edge); }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_VERTEX_H__ */
-
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 6db532faf74..851c67b1189 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -462,7 +462,11 @@ ccl_device_inline float3 operator/=(float3& a, float f)
ccl_device_inline float dot(const float3 a, const float3 b)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7F));
+#else
return a.x*b.x + a.y*b.y + a.z*b.z;
+#endif
}
ccl_device_inline float3 cross(const float3 a, const float3 b)
@@ -475,7 +479,11 @@ ccl_device_inline float3 cross(const float3 a, const float3 b)
ccl_device_inline float len(const float3 a)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(a.m128, a.m128, 0x7F)));
+#else
return sqrtf(dot(a, a));
+#endif
}
ccl_device_inline float len_squared(const float3 a)
@@ -487,7 +495,12 @@ ccl_device_inline float len_squared(const float3 a)
ccl_device_inline float3 normalize(const float3 a)
{
+#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ __m128 norm = _mm_sqrt_ps(_mm_dp_ps(a.m128, a.m128, 0x7F));
+ return _mm_div_ps(a.m128, norm);
+#else
return a/len(a);
+#endif
}
#endif
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index 53603c54da0..61a16b63351 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -86,5 +86,24 @@ void string_split(vector<string>& tokens, const string& str, const string& separ
tokens.push_back(token);
}
+bool string_endswith(const string& s, const char *end)
+{
+ size_t len = strlen(end);
+
+ if(len > s.size())
+ return 0;
+ else
+ return strncmp(s.c_str() + s.size() - len, end, len) == 0;
+}
+
+string string_strip(const string& s)
+{
+ string result = s;
+ result.erase(0, result.find_first_not_of(' '));
+ result.erase(result.find_last_not_of(' ') + 1);
+ return result;
+
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index ee924340716..6808f085834 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -40,6 +40,8 @@ string string_printf(const char *format, ...) PRINTF_ATTRIBUTE;
bool string_iequals(const string& a, const string& b);
void string_split(vector<string>& tokens, const string& str, const string& separators = "\t ");
+bool string_endswith(const string& s, const char *end);
+string string_strip(const string& s);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 345c76bdfab..79bf5fd26b7 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -101,9 +101,7 @@ string system_cpu_brand_string()
replace_string(brand, "(TM)", "");
replace_string(brand, "(R)", "");
- size_t i;
- if((i = brand.find(" ")) != string::npos)
- brand = brand.substr(0, i);
+ brand = string_strip(brand);
return brand;
}
@@ -195,6 +193,11 @@ bool system_cpu_support_sse3()
return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3;
}
+bool system_cpu_support_sse41()
+{
+ CPUCapabilities& caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41;
+}
#else
bool system_cpu_support_sse2()
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 333782c2d01..64cfa4906b3 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -26,6 +26,7 @@ string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_sse2();
bool system_cpu_support_sse3();
+bool system_cpu_support_sse41();
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index c53d67235f6..3fa1df6ab44 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -23,6 +23,12 @@
#endif
+/* Bitness */
+
+#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+#define __KERNEL_64_BIT__
+#endif
+
/* Qualifiers for kernel code shared by CPU and GPU */
#ifndef __KERNEL_GPU__
@@ -34,7 +40,11 @@
#if defined(_WIN32) && !defined(FREE_WINDOWS)
#define ccl_device_inline static __forceinline
+#ifdef __KERNEL_64_BIT__
#define ccl_align(...) __declspec(align(__VA_ARGS__))
+#else
+#define ccl_align(...) /* not support for function arguments (error C2719) */
+#endif
#define ccl_may_alias
#else
#define ccl_device_inline static inline __attribute__((always_inline))
@@ -47,12 +57,6 @@
#endif
-/* Bitness */
-
-#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
-#define __KERNEL_64_BIT__
-#endif
-
/* SIMD Types */
#ifndef __KERNEL_GPU__
@@ -95,6 +99,10 @@
#include <tmmintrin.h> /* SSSE 3 */
#endif
+#ifdef __KERNEL_SSE41__
+#include <smmintrin.h> /* SSE 4.1 */
+#endif
+
#else
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
@@ -199,7 +207,7 @@ struct ccl_align(16) int3 {
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
#else
-struct int3 {
+struct ccl_align(16) int3 {
int x, y, z, w;
#endif
@@ -219,7 +227,7 @@ struct ccl_align(16) int4 {
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
#else
-struct int4 {
+struct ccl_align(16) int4 {
int x, y, z, w;
#endif
@@ -267,7 +275,7 @@ struct ccl_align(16) float3 {
__forceinline operator const __m128&(void) const { return m128; }
__forceinline operator __m128&(void) { return m128; }
#else
-struct float3 {
+struct ccl_align(16) float3 {
float x, y, z, w;
#endif
@@ -287,7 +295,7 @@ struct ccl_align(16) float4 {
__forceinline operator const __m128&(void) const { return m128; }
__forceinline operator __m128&(void) { return m128; }
#else
-struct float4 {
+struct ccl_align(16) float4 {
float x, y, z, w;
#endif
diff --git a/intern/elbeem/intern/ntl_blenderdumper.cpp b/intern/elbeem/intern/ntl_blenderdumper.cpp
index 4efff4337a6..ec05c25004d 100644
--- a/intern/elbeem/intern/ntl_blenderdumper.cpp
+++ b/intern/elbeem/intern/ntl_blenderdumper.cpp
@@ -164,7 +164,7 @@ int ntlBlenderDumper::renderScene( void )
boutfilename << ".bobj.gz";
gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
if (!gzf) {
- errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
+ errMsg("ntlBlenderDumper::renderScene","Unable to open output '" + boutfilename.str() + "' ");
return 1; }
// dont transform velocity output, this is handled in blender
diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp
index 593b582d91f..2f1f5f8efbb 100644
--- a/intern/elbeem/intern/particletracer.cpp
+++ b/intern/elbeem/intern/particletracer.cpp
@@ -233,7 +233,7 @@ void ParticleTracer::checkDumpTextPositions(double simtime) {
if(mDumpTextFile.length()>1) {
boutfilename << mDumpTextFile << ".cpart2";
} else {
- boutfilename << boutfilename <<"_particles" << ".cpart2";
+ boutfilename << "_particles" << ".cpart2";
}
debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"T-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" " , 7);
diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c
index 6f03188a579..3096c589101 100644
--- a/intern/guardedalloc/intern/mmap_win.c
+++ b/intern/guardedalloc/intern/mmap_win.c
@@ -182,14 +182,14 @@ static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
{
struct mmapLink *link = vlink;
- if (link == 0) return;
- if (listbase == 0) return;
+ if (link == NULL) return;
+ if (listbase == NULL) return;
link->next = 0;
link->prev = listbase->last;
if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
- if (listbase->first == 0) listbase->first = link;
+ if (listbase->first == NULL) listbase->first = link;
listbase->last = link;
}
@@ -197,8 +197,8 @@ static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
{
struct mmapLink *link = vlink;
- if (link == 0) return;
- if (listbase == 0) return;
+ if (link == NULL) return;
+ if (listbase == NULL) return;
if (link->next) link->next->prev = link->prev;
if (link->prev) link->prev->next = link->next;
@@ -211,8 +211,8 @@ static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
{
MemMap *mm;
- if (ptr == 0) return NULL;
- if (listbase == 0) return NULL;
+ if (ptr == NULL) return NULL;
+ if (listbase == NULL) return NULL;
mm = (MemMap *)listbase->first;
while (mm) {
diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp
index e6f5fda4066..0c736566b25 100644
--- a/intern/itasc/Armature.cpp
+++ b/intern/itasc/Armature.cpp
@@ -402,7 +402,7 @@ bool Armature::finalize()
m_armlength = 0.0;
for (i=0; i<m_neffector; i++) {
length = 0.0;
- KDL::SegmentMap::const_iterator sit = m_tree.getSegment(m_effectors[i].name);
+ KDL::SegmentMap::value_type const *sit = m_tree.getSegmentPtr(m_effectors[i].name);
while (sit->first != "root") {
Frame tip = sit->second.segment.pose(m_qKdl(sit->second.q_nr));
length += tip.p.Norm();
diff --git a/intern/itasc/kdl/tree.cpp b/intern/itasc/kdl/tree.cpp
index 8776e43f5b4..a31ac79bdf5 100644
--- a/intern/itasc/kdl/tree.cpp
+++ b/intern/itasc/kdl/tree.cpp
@@ -64,7 +64,7 @@ bool Tree::addSegment(const Segment& segment, const std::string& segment_name,
return false;
pair<SegmentMap::iterator, bool> retval;
//insert new element
- TreeElement elem(segment, parent, nrOfJoints);
+ TreeElement elem(segment, *parent, nrOfJoints);
std::pair<std::string, TreeElement> val(segment_name, elem);
retval = segments.insert(val);
diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp
index 82794f96b94..8f971200969 100644
--- a/intern/itasc/kdl/tree.hpp
+++ b/intern/itasc/kdl/tree.hpp
@@ -41,32 +41,28 @@ namespace KDL
{
//Forward declaration
class TreeElement;
-#if defined(__APPLE__)
-# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
typedef std::map<std::string,TreeElement> SegmentMap;
-# else
- // Eigen allocator is needed for alignment of Eigen data types
- typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
-# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#else
// Eigen allocator is needed for alignment of Eigen data types
typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
#endif
+
class TreeElement
{
public:
- TreeElement():q_nr(0)
+ TreeElement():q_nr(0),parent(0)
{};
public:
Segment segment;
unsigned int q_nr;
- SegmentMap::const_iterator parent;
+ SegmentMap::value_type const *parent;
std::vector<SegmentMap::const_iterator > children;
- TreeElement(const Segment& segment_in,const SegmentMap::const_iterator& parent_in,unsigned int q_nr_in)
+ TreeElement(const Segment& segment_in,const SegmentMap::value_type& parent_in,unsigned int q_nr_in)
{
q_nr=q_nr_in;
segment=segment_in;
- parent=parent_in;
+ parent=&parent_in;
};
static TreeElement Root()
{
@@ -167,7 +163,15 @@ namespace KDL
return segments.find(segment_name);
};
+ SegmentMap::value_type const* getSegmentPtr(const std::string& segment_name)const
+ {
+ SegmentMap::const_iterator it = segments.find(segment_name);
+
+ if (it == segments.end())
+ return 0;
+ return &*it;
+ };
const SegmentMap& getSegments()const
{
diff --git a/intern/itasc/kdl/treefksolverpos_recursive.cpp b/intern/itasc/kdl/treefksolverpos_recursive.cpp
index 9103a2165bb..fd78c46f837 100644
--- a/intern/itasc/kdl/treefksolverpos_recursive.cpp
+++ b/intern/itasc/kdl/treefksolverpos_recursive.cpp
@@ -35,22 +35,22 @@ namespace KDL {
int TreeFkSolverPos_recursive::JntToCart(const JntArray& q_in, Frame& p_out, const std::string& segmentName, const std::string& baseName)
{
- SegmentMap::const_iterator it = tree.getSegment(segmentName);
- SegmentMap::const_iterator baseit = tree.getSegment(baseName);
+ SegmentMap::value_type const* it = tree.getSegmentPtr(segmentName);
+ SegmentMap::value_type const* baseit = tree.getSegmentPtr(baseName);
if(q_in.rows() != tree.getNrOfJoints())
return -1;
- else if(it == tree.getSegments().end()) //if the segment name is not found
+ else if(!it) //if the segment name is not found
return -2;
- else if(baseit == tree.getSegments().end()) //if the base segment name is not found
+ else if(!baseit) //if the base segment name is not found
return -3;
else{
- p_out = recursiveFk(q_in, it, baseit);
- return 0;
+ p_out = recursiveFk(q_in, it, baseit);
+ return 0;
}
}
- Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray& q_in, const SegmentMap::const_iterator& it, const SegmentMap::const_iterator& baseit)
+ Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit)
{
//gets the frame for the current element (segment)
const TreeElement& currentElement = it->second;
@@ -60,8 +60,7 @@ namespace KDL {
}
else{
Frame currentFrame = currentElement.segment.pose(((JntArray&)q_in)(currentElement.q_nr));
- SegmentMap::const_iterator parentIt = currentElement.parent;
- return recursiveFk(q_in, parentIt, baseit) * currentFrame;
+ return recursiveFk(q_in, currentElement.parent, baseit) * currentFrame;
}
}
diff --git a/intern/itasc/kdl/treefksolverpos_recursive.hpp b/intern/itasc/kdl/treefksolverpos_recursive.hpp
index c22fe4af75b..2081f23a9ff 100644
--- a/intern/itasc/kdl/treefksolverpos_recursive.hpp
+++ b/intern/itasc/kdl/treefksolverpos_recursive.hpp
@@ -45,7 +45,7 @@ namespace KDL {
private:
const Tree tree;
- Frame recursiveFk(const JntArray& q_in, const SegmentMap::const_iterator& it, const SegmentMap::const_iterator& baseit);
+ Frame recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit);
};
}
diff --git a/intern/itasc/kdl/treejnttojacsolver.cpp b/intern/itasc/kdl/treejnttojacsolver.cpp
index 624bbef7990..e8b4d385ab2 100644
--- a/intern/itasc/kdl/treejnttojacsolver.cpp
+++ b/intern/itasc/kdl/treejnttojacsolver.cpp
@@ -28,16 +28,16 @@ int TreeJntToJacSolver::JntToJac(const JntArray& q_in, Jacobian& jac,
return -1;
//Lets search the tree-element
- SegmentMap::const_iterator it = tree.getSegments().find(segmentname);
+ SegmentMap::value_type const* it = tree.getSegmentPtr(segmentname);
//If segmentname is not inside the tree, back out:
- if (it == tree.getSegments().end())
+ if (!it)
return -2;
//Let's make the jacobian zero:
SetToZero(jac);
- SegmentMap::const_iterator root = tree.getSegments().find("root");
+ SegmentMap::value_type const* root = tree.getSegmentPtr("root");
Frame T_total = Frame::Identity();
Frame T_local, T_joint;
diff --git a/intern/locale/SConscript b/intern/locale/SConscript
index 42941e2105f..4136ac8237d 100644
--- a/intern/locale/SConscript
+++ b/intern/locale/SConscript
@@ -58,9 +58,9 @@ if env['WITH_BF_INTERNATIONAL']:
os.makedirs(build_dir)
msgfmt_tool = env.Clone()
+ msgfmt_tool.Append(LINKFLAGS = env['PLATFORM_LINKFLAGS'])
+
targetpath = root_build_dir + '/msgfmt'
- if env['OURPLATFORM'] == 'darwin':
- msgfmt_tool.Replace( LINKFLAGS = '/usr/lib/libgcc_s.1.dylib /usr/lib/libstdc++.6.dylib /usr/lib/libSystem.B.dylib') # only need these dependencies
msgfmt_target = msgfmt_tool.Program(target = targetpath, source = ['msgfmt.cc'])
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index dec4d0b1c30..32f97a21815 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -138,8 +138,8 @@ public:
typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void *item, int default_priority);
- MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func getDataSize_)
- : getDataSize(getDataSize_) {
+ MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func data_size_func)
+ : data_size_func(data_size_func) {
}
~MEM_CacheLimiter() {
@@ -162,10 +162,16 @@ public:
}
size_t get_memory_in_use() {
- if (getDataSize)
- return total_size();
- else
- return MEM_get_memory_in_use();
+ size_t size = 0;
+ if (data_size_func) {
+ for (iterator it = queue.begin(); it != queue.end(); it++) {
+ size += data_size_func((*it)->get()->get_data());
+ }
+ }
+ else {
+ size = MEM_get_memory_in_use();
+ }
+ return size;
}
void enforce_limits() {
@@ -188,15 +194,15 @@ public:
if (!elem)
break;
- if (getDataSize) {
- cur_size = getDataSize(elem->get()->get_data());
+ if (data_size_func) {
+ cur_size = data_size_func(elem->get()->get_data());
}
else {
cur_size = mem_in_use;
}
if (elem->destroy_if_possible()) {
- if (getDataSize) {
+ if (data_size_func) {
mem_in_use -= cur_size;
}
else {
@@ -207,15 +213,21 @@ public:
}
void touch(MEM_CacheLimiterHandle<T> * handle) {
- queue.push_back(handle);
- queue.erase(handle->me);
- iterator it = queue.end();
- --it;
- handle->me = it;
+ /* If we're using custom priority callback re-arranging the queue
+ * doesn't make much sense because we'll iterate it all to get
+ * least priority element anyway.
+ */
+ if (item_priority_func == NULL) {
+ queue.push_back(handle);
+ queue.erase(handle->me);
+ iterator it = queue.end();
+ --it;
+ handle->me = it;
+ }
}
void set_item_priority_func(MEM_CacheLimiter_ItemPriority_Func item_priority_func) {
- getItemPriority = item_priority_func;
+ this->item_priority_func = item_priority_func;
}
private:
@@ -223,41 +235,42 @@ private:
typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
typedef typename MEM_CacheQueue::iterator iterator;
- size_t total_size() {
- size_t size = 0;
- for (iterator it = queue.begin(); it != queue.end(); it++) {
- size+= getDataSize((*it)->get()->get_data());
- }
- return size;
- }
-
MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
if (queue.empty())
return NULL;
- if (!getItemPriority)
- return *queue.begin();
-
MEM_CacheElementPtr best_match_elem = NULL;
- int best_match_priority = 0;
- iterator it;
- int i;
-
- for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
- MEM_CacheElementPtr elem = *it;
-
- if (!elem->can_destroy())
- continue;
- /* by default 0 means highest priority element */
- /* casting a size type to int is questionable,
- but unlikely to cause problems */
- int priority = -((int)(queue.size()) - i - 1);
- priority = getItemPriority(elem->get()->get_data(), priority);
-
- if (priority < best_match_priority || best_match_elem == NULL) {
- best_match_priority = priority;
+ if (!item_priority_func) {
+ for (iterator it = queue.begin(); it != queue.end(); it++) {
+ MEM_CacheElementPtr elem = *it;
+ if (!elem->can_destroy())
+ continue;
best_match_elem = elem;
+ break;
+ }
+ }
+ else {
+ int best_match_priority = 0;
+ iterator it;
+ int i;
+
+ for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
+ MEM_CacheElementPtr elem = *it;
+
+ if (!elem->can_destroy())
+ continue;
+
+ /* by default 0 means highest priority element */
+ /* casting a size type to int is questionable,
+ but unlikely to cause problems */
+ int priority = -((int)(queue.size()) - i - 1);
+ priority = item_priority_func(elem->get()->get_data(), priority);
+
+ if (priority < best_match_priority || best_match_elem == NULL) {
+ best_match_priority = priority;
+ best_match_elem = elem;
+ }
}
}
@@ -265,8 +278,8 @@ private:
}
MEM_CacheQueue queue;
- MEM_CacheLimiter_DataSize_Func getDataSize;
- MEM_CacheLimiter_ItemPriority_Func getItemPriority;
+ MEM_CacheLimiter_DataSize_Func data_size_func;
+ MEM_CacheLimiter_ItemPriority_Func item_priority_func;
};
-#endif // __MEM_CACHELIMITER_H__
+#endif // __MEM_CACHELIMITER_H__
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index ca999eab569..6383bbbb07f 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -431,3 +431,13 @@ void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState * /*state*/)
void FallbackImpl::freeGLState(struct OCIO_GLSLDrawState * /*state_r*/)
{
}
+
+const char *FallbackImpl::getVersionString(void)
+{
+ return "fallback";
+}
+
+int FallbackImpl::getVersionHex(void)
+{
+ return 0;
+}
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 30668dff245..47ee3afddfd 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -338,3 +338,13 @@ void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state)
{
impl->freeGLState(state);
}
+
+const char *OCIO_getVersionString(void)
+{
+ return impl->getVersionString();
+}
+
+int OCIO_getVersionHex(void)
+{
+ return impl->getVersionHex();
+}
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 5532ade1f3a..5abe104fcd4 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -193,6 +193,9 @@ int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorR
void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
+const char *OCIO_getVersionString(void);
+int OCIO_getVersionHex(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 2cffe1a89ef..663ca2d1c75 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -609,3 +609,13 @@ void OCIOImpl::matrixTransformScale(float *m44, float *offset4, const float *sca
{
MatrixTransform::Scale(m44, offset4, scale4f);
}
+
+const char *OCIOImpl::getVersionString(void)
+{
+ return GetVersion();
+}
+
+int OCIOImpl::getVersionHex(void)
+{
+ return GetVersionHex();
+}
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 8b666e8ae14..4e7c1bcc832 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -110,6 +110,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide) = 0;
virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
+
+ virtual const char *getVersionString(void) = 0;
+ virtual int getVersionHex(void) = 0;
};
class FallbackImpl : public IOCIOImpl {
@@ -194,6 +197,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
+
+ const char *getVersionString(void);
+ int getVersionHex(void);
};
#ifdef WITH_OCIO
@@ -279,6 +285,9 @@ public:
OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
void freeGLState(struct OCIO_GLSLDrawState *state_r);
+
+ const char *getVersionString(void);
+ int getVersionHex(void);
};
#endif
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png
deleted file mode 100644
index 855f06f4fb9..00000000000
--- a/release/scripts/freestyle/data/env_map/brown00.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png
deleted file mode 100644
index 7c9b1a8149e..00000000000
--- a/release/scripts/freestyle/data/env_map/gray00.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png
deleted file mode 100644
index 06542908e6b..00000000000
--- a/release/scripts/freestyle/data/env_map/gray01.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png
deleted file mode 100644
index 0208f4920d9..00000000000
--- a/release/scripts/freestyle/data/env_map/gray02.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png
deleted file mode 100644
index aab9b957c21..00000000000
--- a/release/scripts/freestyle/data/env_map/gray03.png
+++ /dev/null
Binary files differ
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
index 429fea60d7a..6fea14b3df4 100644
--- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -791,7 +791,7 @@ def dump_src_messages(msgs, reports, settings):
##### Main functions! #####
def dump_messages(do_messages, do_checks, settings):
bl_ver = "Blender " + bpy.app.version_string
- bl_hash = bpy.app.build_hash or b'0000000000000000000000000000000000000000'
+ bl_hash = bpy.app.build_hash
bl_date = datetime.datetime.strptime(bpy.app.build_date.decode() + "T" + bpy.app.build_time.decode(),
"%Y-%m-%dT%H:%M:%S")
pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, bl_ver, bl_hash, bl_date, bl_date.year,
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index 4b673b2e0de..45091fcf1eb 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -60,6 +60,7 @@ KM_HIERARCHY = [
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
+ ('View3D Walk Modal', 'EMPTY', 'WINDOW', []),
('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
('View3D Move Modal', 'EMPTY', 'WINDOW', []),
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 83f2647c5b2..1785ab59a5f 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -118,6 +118,36 @@ def write_sysinfo(op):
else:
output.write("Blender was built without FFmpeg support\n")
+ output.write("\nOther Libraries:\n")
+ output.write(lilies)
+ ocio = bpy.app.ocio
+ output.write("OpenColorIO: ")
+ if ocio.supported:
+ if ocio.version_string == "fallback":
+ output.write("Blender was built with OpenColorIO, " +
+ "but it currently uses fallback color management.\n")
+ else:
+ output.write("%s\n" % (ocio.version_string))
+ else:
+ output.write("Blender was built without OpenColorIO support\n")
+
+ oiio = bpy.app.oiio
+ output.write("OpenImageIO: ")
+ if ocio.supported :
+ output.write("%s\n" % (oiio.version_string))
+ else:
+ output.write("Blender was built without OpenImageIO support\n")
+
+ output.write("OpenShadingLanguage: ")
+ if bpy.app.build_options.cycles:
+ if bpy.app.build_options.cycles_osl:
+ from _cycles import osl_version_string
+ output.write("%s\n" % (osl_version_string))
+ else:
+ output.write("Blender was built without OpenShadingLanguage support in Cycles\n")
+ else:
+ output.write("Blender was built without Cycles support\n")
+
if bpy.app.background:
output.write("\nOpenGL: missing, background mode\n")
else:
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 89147c1c210..4244ebb283b 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -496,6 +496,8 @@
vertex_select="#ff8500"
vertex_size="3"
vertex_unreferenced="#000000"
+ wire_edit="#C0C0C0"
+ edge_select="#FF8500"
face="#ffffff0a"
face_select="#ff85003c"
face_dot="#ff8500"
@@ -663,9 +665,17 @@
wire_select="#0019ff"
selected_text="#7f7070"
node_backdrop="#202030bc"
- in_out_node="#273053"
+ input_node="#273053"
+ output_node="#273053"
converter_node="#113941"
- operator_node="#0e3157"
+ color_node="#0e3157"
+ filter_node="#0e3157"
+ vector_node="#0e3157"
+ texture_node="#0e3157"
+ shader_node="#0e3157"
+ script_node="#0e3157"
+ pattern_node="#0e3157"
+ layout_node="#0e3157"
group_node="#091a07"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index cedeeac38e6..def6f52425a 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -496,6 +496,8 @@
vertex_select="#ff8500"
vertex_size="3"
vertex_unreferenced="#000000"
+ wire_edit="#C0C0C0"
+ edge_select="#FF8500"
face="#ffffff0a"
face_select="#ff85003c"
face_dot="#ff8500"
@@ -663,9 +665,17 @@
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9b9ba0"
- in_out_node="#646464"
+ input_node="#646464"
+ output_node="#646464"
+ color_node="#6c696f"
+ filter_node="#6c696f"
+ vector_node="#6c696f"
+ texture_node="#6c696f"
+ shader_node="#6c696f"
+ script_node="#6c696f"
+ pattern_node="#6c696f"
+ layout_node="#6c696f"
converter_node="#686a75"
- operator_node="#6c696f"
group_node="#69756e"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index 60de59e2e10..498eca237f4 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -496,6 +496,8 @@
vertex_select="#be6925"
vertex_size="3"
vertex_unreferenced="#000000"
+ wire_edit="#C0C0C0"
+ edge_select="#FF8500"
face="#a47c5b0a"
face_select="#a47c5b3c"
face_dot="#ffffff"
@@ -663,9 +665,17 @@
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9b9ba0"
- in_out_node="#e08706"
converter_node="#575675"
- operator_node="#2c6f6f"
+ input_node="#e08706"
+ output_node="#e08706"
+ color_node="#2c6f6f"
+ filter_node="#2c6f6f"
+ vector_node="#2c6f6f"
+ texture_node="#2c6f6f"
+ shader_node="#2c6f6f"
+ script_node="#2c6f6f"
+ pattern_node="#2c6f6f"
+ layout_node="#2c6f6f"
group_node="#1e7524"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index 277215ac831..404cbd82f5c 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -496,6 +496,8 @@
vertex_select="#50c8ff"
vertex_size="3"
vertex_unreferenced="#000000"
+ wire_edit="#C0C0C0"
+ edge_select="#FF8500"
face="#ffffff0a"
face_select="#50c8ff3c"
face_dot="#50c8ff"
@@ -663,9 +665,17 @@
wire_select="#ffffff"
selected_text="#7f7070"
node_backdrop="#9b9baca0"
- in_out_node="#64647b"
converter_node="#686a84"
- operator_node="#6c697e"
+ input_node="#64647b"
+ output_node="#64647b"
+ color_node="#6c697e"
+ filter_node="#6c697e"
+ vector_node="#6c697e"
+ texture_node="#6c697e"
+ shader_node="#6c697e"
+ script_node="#6c697e"
+ pattern_node="#6c697e"
+ layout_node="#6c697e"
group_node="#69756e"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
index 0b01d42f65a..b21a4f7c933 100644
--- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
+++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
@@ -496,6 +496,8 @@
vertex_select="#f47421"
vertex_size="3"
vertex_unreferenced="#000000"
+ wire_edit="#C0C0C0"
+ edge_select="#FF8500"
face="#ffffff0a"
face_select="#ff85003c"
face_dot="#f47421"
@@ -663,9 +665,17 @@
wire_select="#f4b696"
selected_text="#7f7070"
node_backdrop="#52524ed1"
- in_out_node="#f40051"
converter_node="#93be00"
- operator_node="#000000"
+ input_node="#f40051"
+ output_node="#f40051"
+ color_node="#000000"
+ filter_node="#000000"
+ vector_node="#000000"
+ texture_node="#000000"
+ shader_node="#000000"
+ script_node="#000000"
+ pattern_node="#000000"
+ layout_node="#000000"
group_node="#19b6ee"
group_socket_node="#dfca35"
frame_node="#9a9b9ba0"
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 0814d0144ab..13189b2e9d3 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -97,9 +97,6 @@ class NodeAddOperator():
print(str(e))
# Continue despite invalid attribute
- if space.use_hidden_preview:
- node.show_preview = False
-
node.select = True
tree.nodes.active = node
node.location = space.cursor_location
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index a274453a472..f27087a48b0 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -136,10 +136,6 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
- col = layout.column()
- col.active = (ob.proxy is None)
- col.prop(group, "name")
-
split = layout.split()
split.active = (ob.proxy is None)
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 2171ce67fd3..ea0b3d80bd1 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -21,6 +21,8 @@ import bpy
from bpy.types import Panel
from rna_prop_ui import PropertyPanel
+from bpy.types import Curve, SurfaceCurve, TextCurve
+
class CurveButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -29,15 +31,25 @@ class CurveButtonsPanel():
@classmethod
def poll(cls, context):
- return (context.object and context.object.type in {'CURVE', 'SURFACE', 'FONT'} and context.curve)
+ return (context.curve is not None)
class CurveButtonsPanelCurve(CurveButtonsPanel):
- """Same as above but for curves only"""
+ @classmethod
+ def poll(cls, context):
+ return (type(context.curve) is Curve)
+
+
+class CurveButtonsPanelSurface(CurveButtonsPanel):
+ @classmethod
+ def poll(cls, context):
+ return (type(context.curve) is SurfaceCurve)
+
+class CurveButtonsPanelText(CurveButtonsPanel):
@classmethod
def poll(cls, context):
- return (context.object and context.object.type == 'CURVE' and context.curve)
+ return (type(context.curve) is TextCurve)
class CurveButtonsPanelActive(CurveButtonsPanel):
@@ -46,7 +58,7 @@ class CurveButtonsPanelActive(CurveButtonsPanel):
@classmethod
def poll(cls, context):
curve = context.curve
- return (curve and type(curve) is not bpy.types.TextCurve and curve.splines.active)
+ return (curve and type(curve) is not TextCurve and curve.splines.active)
class DATA_PT_context_curve(CurveButtonsPanel, Panel):
@@ -56,14 +68,14 @@ class DATA_PT_context_curve(CurveButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- ob = context.object
+ obj = context.object
curve = context.curve
space = context.space_data
- if ob:
- layout.template_ID(ob, "data")
+ if obj:
+ layout.template_ID(obj, "data")
elif curve:
- layout.template_ID(space, "pin_id") # XXX: broken
+ layout.template_ID(space, "pin_id")
class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
@@ -72,11 +84,10 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- ob = context.object
curve = context.curve
- is_surf = (ob.type == 'SURFACE')
- is_curve = (ob.type == 'CURVE')
- is_text = (ob.type == 'FONT')
+ is_surf = type(curve) is SurfaceCurve
+ is_curve = type(curve) is Curve
+ is_text = type(curve) is TextCurve
if is_curve:
row = layout.row()
@@ -140,17 +151,11 @@ class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel):
row.column().prop(curve, "texspace_location", text="Location")
row.column().prop(curve, "texspace_size", text="Size")
+ layout.operator("curve.match_texture_space")
-class DATA_PT_geometry_curve(CurveButtonsPanel, Panel):
- bl_label = "Geometry"
- @classmethod
- def poll(cls, context):
- obj = context.object
- if obj and obj.type == 'SURFACE':
- return False
-
- return context.curve
+class DATA_PT_geometry_curve(CurveButtonsPanelSurface, Panel):
+ bl_label = "Geometry"
def draw(self, context):
layout = self.layout
@@ -214,10 +219,9 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
def draw(self, context):
layout = self.layout
- ob = context.object
curve = context.curve
act_spline = curve.splines.active
- is_surf = (ob.type == 'SURFACE')
+ is_surf = type(curve) is SurfaceCurve
is_poly = (act_spline.type == 'POLY')
split = layout.split()
@@ -279,13 +283,9 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
layout.prop(act_spline, "use_smooth")
-class DATA_PT_font(CurveButtonsPanel, Panel):
+class DATA_PT_font(CurveButtonsPanelText, Panel):
bl_label = "Font"
- @classmethod
- def poll(cls, context):
- return (context.object and context.object.type == 'FONT' and context.curve)
-
def draw(self, context):
layout = self.layout
@@ -307,10 +307,6 @@ class DATA_PT_font(CurveButtonsPanel, Panel):
#layout.prop(text, "font")
- row = layout.split(percentage=0.25)
- row.label(text="Body Text:")
- row.prop(text, "body", text="")
-
split = layout.split()
col = split.column()
@@ -347,13 +343,9 @@ class DATA_PT_font(CurveButtonsPanel, Panel):
row.prop(char, "use_small_caps")
-class DATA_PT_paragraph(CurveButtonsPanel, Panel):
+class DATA_PT_paragraph(CurveButtonsPanelText, Panel):
bl_label = "Paragraph"
- @classmethod
- def poll(cls, context):
- return (context.object and context.object.type == 'FONT' and context.curve)
-
def draw(self, context):
layout = self.layout
@@ -376,13 +368,9 @@ class DATA_PT_paragraph(CurveButtonsPanel, Panel):
col.prop(text, "offset_y", text="Y")
-class DATA_PT_text_boxes(CurveButtonsPanel, Panel):
+class DATA_PT_text_boxes(CurveButtonsPanelText, Panel):
bl_label = "Text Boxes"
- @classmethod
- def poll(cls, context):
- return (context.object and context.object.type == 'FONT' and context.curve)
-
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index f59d479c509..edf3354db4f 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -64,7 +64,7 @@ class MESH_UL_vgroups(UIList):
# assert(isinstance(item, bpy.types.VertexGroup)
vgroup = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=vgroup.name, translate=False, icon_value=icon)
+ layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
elif self.layout_type in {'GRID'}:
@@ -80,7 +80,7 @@ class MESH_UL_shape_keys(UIList):
key_block = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
split = layout.split(0.66, False)
- split.label(text=item.name, translate=False, icon_value=icon)
+ split.prop(key_block, "name", text="", emboss=False, icon_value=icon)
row = split.row(align=True)
if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
row.active = False
@@ -98,7 +98,7 @@ class MESH_UL_uvmaps_vcols(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer))
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=item.name, translate=False, icon_value=icon)
+ layout.prop(item, "name", text="", emboss=False, icon_value=icon)
icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
layout.prop(item, "active_render", text="", icon=icon, emboss=False)
elif self.layout_type in {'GRID'}:
@@ -191,7 +191,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
ob = context.object
group = ob.vertex_groups.active
- rows = 1
+ rows = 2
if group:
rows = 4
@@ -207,9 +207,6 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
- row = layout.row()
- row.prop(group, "name")
-
if ob.vertex_groups and (ob.mode == 'EDIT' or (ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex)):
row = layout.row()
@@ -250,7 +247,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
row = layout.row()
- rows = 1
+ rows = 2
if kb:
rows = 4
row.template_list("MESH_UL_shape_keys", "", key, "key_blocks", ob, "active_shape_key_index", rows=rows)
@@ -290,9 +287,6 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
else:
sub.operator("object.shape_key_retime", icon='RECOVER_LAST', text="")
- row = layout.row()
- row.prop(kb, "name")
-
if key.use_relative:
if ob.active_shape_key_index != 0:
row = layout.row()
@@ -340,9 +334,6 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
col.operator("mesh.uv_texture_remove", icon='ZOOMOUT', text="")
- if lay:
- layout.prop(lay, "name")
-
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
@@ -363,9 +354,6 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
col.operator("mesh.vertex_color_add", icon='ZOOMIN', text="")
col.operator("mesh.vertex_color_remove", icon='ZOOMOUT', text="")
- if lay:
- layout.prop(lay, "name")
-
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 7e892240d44..caf71de9bb9 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -675,6 +675,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_normal_calculate")
col.prop(md, "use_normal_flip")
col.prop(md, "iterations")
+ col.prop(md, "use_stretch_u")
+ col.prop(md, "use_stretch_v")
def SHRINKWRAP(self, layout, ob, md):
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index a57567ae79e..87a08104c5d 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -97,7 +97,7 @@ class RENDERLAYER_UL_linesets(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
lineset = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(lineset.name, icon_value=icon)
+ layout.prop(lineset, "name", text="", emboss=False, icon_value=icon)
layout.prop(lineset, "show_render", text="", index=index)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
@@ -193,7 +193,7 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
layout.active = rl.use_freestyle
row = layout.row()
- rows = 4 if lineset else 1
+ rows = 4 if lineset else 2
row.template_list("RENDERLAYER_UL_linesets", "", freestyle, "linesets", freestyle.linesets, "active_index", rows=rows)
sub = row.column(align=True)
@@ -206,8 +206,6 @@ class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, P
sub.operator("scene.freestyle_lineset_move", icon='TRIA_UP', text="").direction = 'UP'
sub.operator("scene.freestyle_lineset_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
- layout.prop(lineset, "name")
-
col = layout.column()
col.label(text="Selection By:")
row = col.row(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 3470c9577af..fdbe02ebd47 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -156,6 +156,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
col = layout.column()
col.prop(game, "use_actor")
col.prop(game, "use_ghost")
+ col.prop(game, "use_record_animation")
col.prop(ob, "hide_render", text="Invisible")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 203e5078ee4..fb7a3d8b303 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -31,7 +31,7 @@ class MASK_UL_layers(UIList):
# assert(isinstance(item, bpy.types.MaskLayer)
mask = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=mask.name, translate=False, icon_value=icon)
+ layout.prop(mask, "name", text="", emboss=False, icon_value=icon)
row = layout.row(align=True)
row.prop(mask, "hide", text="", emboss=False)
row.prop(mask, "hide_select", text="", emboss=False)
@@ -99,8 +99,6 @@ class MASK_PT_layers:
sub.operator("mask.layer_move", icon='TRIA_UP', text="").direction = 'UP'
sub.operator("mask.layer_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
- layout.prop(active_layer, "name")
-
# blending
row = layout.row(align=True)
row.prop(active_layer, "alpha")
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 344074c5893..d48c4957e6e 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -77,7 +77,10 @@ class MATERIAL_UL_matslots(UIList):
slot = item
ma = slot.material
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ if ma:
+ layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
+ else:
+ layout.label(text="", icon_value=icon)
if ma and not context.scene.render.use_shading_nodes:
manode = ma.active_node_material
if manode:
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index f8a37e2768f..206a208eac3 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -122,33 +122,25 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
split = layout.split(percentage=0.32)
col = split.column()
- col.label(text="Name:")
col.label(text="Settings:")
col = split.column()
- col.prop(psys, "name", text="")
col.template_ID(psys, "settings", new="particle.new")
else:
part = psys.settings
split = layout.split(percentage=0.32)
col = split.column()
- col.label(text="Name:")
if part.is_fluid is False:
col.label(text="Settings:")
col.label(text="Type:")
col = split.column()
- col.prop(psys, "name", text="")
if part.is_fluid is False:
row = col.row()
row.enabled = particle_panel_enabled(context, psys)
row.template_ID(psys, "settings", new="particle.new")
- #row = layout.row()
- #row.label(text="Viewport")
- #row.label(text="Render")
-
if part.is_fluid:
layout.label(text=iface_("%d fluid particles for this frame") % part.count, translate=False)
return
@@ -805,7 +797,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
part = particle_get_settings(context)
row = layout.row()
- row.prop(part, "material")
+ row.prop(part, "material_slot", text="")
if psys:
row.prop(psys, "parent")
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index f0c7a532414..06c04f25c62 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -33,7 +33,7 @@ class PHYSICS_UL_dynapaint_surfaces(UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
row = layout.row(align=True)
row.label(text="", icon_value=icon)
- row.label(text=surf.name, translate=False, icon_value=sticon)
+ row.prop(surf, "name", text="", emboss=False, icon_value=sticon)
row = layout.row(align=True)
if surf.use_color_preview:
row.prop(surf, "show_preview", text="", emboss=False,
@@ -87,7 +87,6 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
col.operator("dpaint.surface_slot_remove", icon='ZOOMOUT', text="")
if surface:
- layout.prop(surface, "name")
layout.prop(surface, "surface_format")
col = layout.column()
@@ -324,7 +323,8 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
ob = context.object
layout.prop(surface, "init_color_type", expand=False)
- layout.separator()
+ if surface.init_color_type != 'NONE':
+ layout.separator()
# dissolve
if surface.init_color_type == 'COLOR':
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index dcc4508f086..133b4f986aa 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -38,7 +38,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
# assert(isinstance(item, bpy.types.SceneRenderLayer)
layer = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(layer.name, icon_value=icon, translate=False)
+ layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
layout.prop(layer, "use", text="", index=index)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
@@ -58,17 +58,13 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=1)
+ col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
- col = row.column(align=True)
- col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
- col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- rl = rd.layers.active
- if rl:
- row.prop(rl, "name")
- row.prop(rd, "use_single_layer", text="", icon_only=True)
+ col = row.column()
+ sub = col.column(align=True)
+ sub.operator("scene.render_layer_add", icon='ZOOMIN', text="")
+ sub.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
+ col.prop(rd, "use_single_layer", text="", icon_only=True)
class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 91a5abd0ad0..10574c88abb 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -33,6 +33,7 @@ class SCENE_UL_keying_set_paths(UIList):
kspath = item
icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # Do not make this one editable in uiList for now...
layout.label(text=kspath.data_path, translate=False, icon_value=icon)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
@@ -105,14 +106,13 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.prop(ks, "bl_label")
col.prop(ks, "bl_description")
subcol = col.column()
subcol.operator_context = 'INVOKE_DEFAULT'
subcol.operator("anim.keying_set_export", text="Export to File").filepath = "keyingset.py"
- col = row.column(align=True)
+ col = row.column()
col.label(text="Keyframing Settings:")
col.prop(ks, "bl_options")
@@ -168,7 +168,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
if ksp.group_method == 'NAMED':
col.prop(ksp, "group")
- col = row.column(align=True)
+ col = row.column()
col.label(text="Keyframing Settings:")
col.prop(ksp, "bl_options")
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 023b3a13848..c03ea1c5422 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -63,7 +63,10 @@ class TEXTURE_UL_texslots(UIList):
slot = item
tex = slot.texture if slot else None
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=tex.name if tex else "", translate=False, icon_value=icon)
+ if tex:
+ layout.prop(tex, "name", text="", emboss=False, icon_value=icon)
+ else:
+ layout.label(text="", icon_value=icon)
if tex and isinstance(item, bpy.types.MaterialTextureSlot):
layout.prop(ma, "use_textures", text="", index=index)
elif self.layout_type in {'GRID'}:
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 3db8697a457..d6a63c6497b 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -29,9 +29,9 @@ class CLIP_UL_tracking_objects(UIList):
# assert(isinstance(item, bpy.types.MovieTrackingObject)
tobj = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(text=tobj.name, translate=False,
- icon='CAMERA_DATA' if tobj.is_camera
- else 'OBJECT_DATA')
+ layout.prop(tobj, "name", text="", emboss=False,
+ icon='CAMERA_DATA' if tobj.is_camera
+ else 'OBJECT_DATA')
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label(text="",
@@ -506,10 +506,6 @@ class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
sub.operator("clip.tracking_object_new", icon='ZOOMIN', text="")
sub.operator("clip.tracking_object_remove", icon='ZOOMOUT', text="")
- active = tracking.objects.active
- if active:
- layout.prop(active, "name")
-
class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
@@ -596,6 +592,11 @@ class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel):
layout.prop(active_track, "name")
layout.prop(active_track, "use_auto_keying")
+ layout.prop(active_track, "image")
+
+ row = layout.row()
+ row.active = active_track.image is not None
+ row.prop(active_track, "image_opacity", text="Opacity")
class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 397b74116c2..c9a79575ef0 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -19,7 +19,11 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-from bl_ui.properties_paint_common import UnifiedPaintPanel, brush_texture_settings, brush_mask_texture_settings
+from bl_ui.properties_paint_common import (
+ UnifiedPaintPanel,
+ brush_texture_settings,
+ brush_mask_texture_settings,
+ )
from bpy.app.translations import pgettext_iface as iface_
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index a7a648e3c44..e1f04a74ac5 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -83,6 +83,7 @@ class INFO_MT_file(Menu):
bl_label = "File"
def draw(self, context):
+ import sys
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
@@ -131,6 +132,8 @@ class INFO_MT_file(Menu):
layout.separator()
layout.operator_context = 'EXEC_AREA'
+ if sys.platform == "darwin":
+ layout.operator_context = 'INVOKE_SCREEN' # quit dialog
layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 46234b638eb..3bf2977d778 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -395,7 +395,6 @@ class NODE_PT_quality(bpy.types.Panel):
col.prop(tree, "use_two_pass")
col.prop(tree, "use_viewer_border")
col.prop(snode, "show_highlight")
- col.prop(snode, "use_hidden_preview")
class NODE_UL_interface_sockets(bpy.types.UIList):
@@ -410,7 +409,7 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
if not socket.is_output:
row.template_node_socket(color)
- row.label(text=socket.name, icon_value=icon)
+ row.prop(socket, "name", text="", emboss=False, icon_value=icon)
# outputs get icon on the right
if socket.is_output:
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index e21656c3259..acd4fc87de4 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -210,11 +210,15 @@ class USERPREF_PT_interface(Panel):
col.label(text="Menus:")
col.prop(view, "use_mouse_over_open")
- col.label(text="Menu Open Delay:")
- col.prop(view, "open_toplevel_delay", text="Top Level")
- col.prop(view, "open_sublevel_delay", text="Sub Level")
+ sub = col.column()
+ sub.active = view.use_mouse_over_open
+
+ sub.prop(view, "open_toplevel_delay", text="Top Level")
+ sub.prop(view, "open_sublevel_delay", text="Sub Level")
col.separator()
+ col.separator()
+ col.separator()
col.prop(view, "show_splash")
@@ -1049,6 +1053,28 @@ class USERPREF_PT_input(Panel):
col.separator()
sub = col.column()
+ sub.label(text="View Navigation:")
+ sub.row().prop(inputs, "navigation_mode", expand=True)
+ if inputs.navigation_mode == 'WALK':
+ walk = inputs.walk_navigation
+
+ sub.prop(walk, "use_mouse_reverse")
+ sub.prop(walk, "mouse_speed")
+ sub.prop(walk, "teleport_time")
+
+ sub = col.column(align=True)
+ sub.prop(walk, "walk_speed")
+ sub.prop(walk, "walk_speed_factor")
+
+ sub.separator()
+ sub.prop(walk, "use_gravity")
+ sub = col.column(align=True)
+ sub.active = walk.use_gravity
+ sub.prop(walk, "view_height")
+ sub.prop(walk, "jump_height")
+
+ col.separator()
+ sub = col.column()
sub.label(text="NDOF Device:")
sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
sub.prop(inputs, "ndof_orbit_sensitivity", text="NDOF Orbit Sensitivity")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index d7f60e00633..296a428e1d3 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -435,6 +435,7 @@ class VIEW3D_MT_view_navigation(Menu):
layout.separator()
layout.operator("view3d.fly")
+ layout.operator("view3d.walk")
class VIEW3D_MT_view_align(Menu):
@@ -745,6 +746,7 @@ class VIEW3D_MT_select_edit_lattice(Menu):
layout.separator()
+ layout.operator("lattice.select_mirror")
layout.operator("lattice.select_random")
layout.operator("lattice.select_all").action = 'TOGGLE'
layout.operator("lattice.select_all", text="Inverse").action = 'INVERT'
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index cd3c238fe86..bdf7b8ea137 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -19,9 +19,11 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu, Panel
-from bl_ui.properties_paint_common import UnifiedPaintPanel
-from bl_ui.properties_paint_common import brush_texture_settings
-from bl_ui.properties_paint_common import brush_mask_texture_settings
+from bl_ui.properties_paint_common import (
+ UnifiedPaintPanel,
+ brush_texture_settings,
+ brush_mask_texture_settings,
+ )
class View3DPanel():
@@ -88,7 +90,7 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Object:")
- col.operator("object.duplicate_move")
+ col.operator("object.duplicate_move", text="Duplicate")
col.operator("object.delete")
col.operator("object.join")
@@ -986,6 +988,8 @@ class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
+ settings = self.paint_settings(context)
+ brush = settings.brush
if context.sculpt_object.use_dynamic_topology_sculpting:
layout.operator("sculpt.dynamic_topology_toggle", icon='X', text="Disable Dynamic")
@@ -994,9 +998,12 @@ class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
col = layout.column()
col.active = context.sculpt_object.use_dynamic_topology_sculpting
- col.prop(sculpt, "detail_size")
+ sub = col.column(align=True)
+ sub.active = brush and brush.sculpt_tool not in ('MASK')
+ sub.prop(sculpt, "detail_size")
+ sub.prop(sculpt, "detail_refine_method", text="")
+ col.separator()
col.prop(sculpt, "use_smooth_shading")
- col.prop(sculpt, "use_edge_collapse")
col.operator("sculpt.optimize")
col.separator()
col.prop(sculpt, "symmetrize_direction")
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 71ff547f6da..675d0ab8489 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -111,6 +111,7 @@ shader_node_categories = [
ShaderOldNodeCategory("SH_INPUT", "Input", items=[
NodeItem("ShaderNodeMaterial"),
NodeItem("ShaderNodeCameraData"),
+ NodeItem("ShaderNodeLampData"),
NodeItem("ShaderNodeValue"),
NodeItem("ShaderNodeRGB"),
NodeItem("ShaderNodeTexture"),
@@ -141,6 +142,8 @@ shader_node_categories = [
NodeItem("ShaderNodeSqueeze"),
NodeItem("ShaderNodeSeparateRGB"),
NodeItem("ShaderNodeCombineRGB"),
+ NodeItem("ShaderNodeSeparateHSV"),
+ NodeItem("ShaderNodeCombineHSV"),
]),
ShaderOldNodeCategory("SH_GROUP", "Group", items=node_group_items),
ShaderOldNodeCategory("SH_LAYOUT", "Layout", items=[
diff --git a/release/scripts/templates_osl/gabor_noise.osl b/release/scripts/templates_osl/gabor_noise.osl
new file mode 100644
index 00000000000..1f5910685d2
--- /dev/null
+++ b/release/scripts/templates_osl/gabor_noise.osl
@@ -0,0 +1,17 @@
+
+shader gabor_noise(
+ point Point = P,
+ vector Direction = vector(1, 0, 0),
+ int Anisotropic = 0,
+ float Bandwidth = 1.0,
+ float Impulses = 16,
+ output float Gabor = 0.8)
+{
+ Gabor = noise("gabor", Point,
+ "direction", Direction,
+ "anisotropic", Anisotropic,
+ "do_filter", 1, // Set to 0 to disable filtering/anti-aliasing
+ "bandwidth", Bandwidth,
+ "impulses", Impulses);
+}
+
diff --git a/release/scripts/templates_osl/noise.osl b/release/scripts/templates_osl/noise.osl
index 05cc31687c0..a4ffbbc1ee7 100644
--- a/release/scripts/templates_osl/noise.osl
+++ b/release/scripts/templates_osl/noise.osl
@@ -4,15 +4,24 @@ shader noise(
point Point = P,
output float Cell = 0.0,
output color Perlin = 0.8,
- output color UPerlin = 0.8)
+ output color UPerlin = 0.8,
+ output color Simplex = 0.8,
+ output color USimplex = 0.8)
{
/* Cell Noise */
Cell = noise("cell", Point);
+
+ /* Perlin 4D Noise */
+ Perlin = noise("perlin", Point, Time);
+
+ /* UPerlin 4D Noise */
+ UPerlin = noise("uperlin", Point, Time);
+
+ /* Simplex 4D Noise */
+ Simplex = noise("simplex", Point, Time);
+
+ /* USimplex 4D Noise */
+ USimplex = noise("usimplex", Point, Time);
- /* Perlin 4D Noise*/
- Perlin = noise("perlin", Point, Time);
-
- /* UPerlin 4D Noise*/
- UPerlin = noise("uperlin", Point, Time);
}
diff --git a/release/scripts/templates_osl/temperature_to_rgb.osl b/release/scripts/templates_osl/temperature_to_rgb.osl
deleted file mode 100644
index 6b91416c609..00000000000
--- a/release/scripts/templates_osl/temperature_to_rgb.osl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-shader temperature_to_rgb(
- float Kelvin = 1200.0,
- output color Color = 0.8)
-{
- /* Kelvin to RGB */
- Color = blackbody(Kelvin);
-}
-
diff --git a/release/scripts/templates_osl/wavelength_to_rgb.osl b/release/scripts/templates_osl/wavelength_to_rgb.osl
deleted file mode 100644
index 2a605be101d..00000000000
--- a/release/scripts/templates_osl/wavelength_to_rgb.osl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-shader wavelength_to_rgb(
- float Wavelength = 500.0,
- output color Color = 0.8)
-{
- /* Wavelength to RGB */
- Color = wavelength_color(Wavelength);
-}
-
diff --git a/release/scripts/templates_osl/wireframe.osl b/release/scripts/templates_osl/wireframe.osl
deleted file mode 100644
index 00e4506e73c..00000000000
--- a/release/scripts/templates_osl/wireframe.osl
+++ /dev/null
@@ -1,11 +0,0 @@
-
-#include "oslutil.h"
-
-shader wireframe(
- float Line_Width = 2.0,
- int Raster = 1,
- output float Wire = 0.0)
-{
- Wire = wireframe("triangles", Line_Width, Raster);
-}
-
diff --git a/release/scripts/templates_py/ui_list_simple.py b/release/scripts/templates_py/ui_list_simple.py
index 815d62ad734..e911a0dd236 100644
--- a/release/scripts/templates_py/ui_list_simple.py
+++ b/release/scripts/templates_py/ui_list_simple.py
@@ -20,11 +20,14 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
ma = slot.material
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
if self.layout_type in {'DEFAULT', 'COMPACT'}:
- # You should always start your row layout by a label (icon + text), this will also make the row easily
- # selectable in the list!
+ # You should always start your row layout by a label (icon + text), or a non-embossed text field,
+ # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
- layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ if ma:
+ layout.prop(ma, "name", text="", emboss=False, icon_value=icon)
+ else:
+ layout.label(text="", translate=False, icon_value=icon)
# And now we can add other UI stuff...
# Here, we add nodes info if this material uses (old!) shading nodes.
if ma and not context.scene.render.use_shading_nodes:
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 8f77f8c984d..b25166f4b18 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -82,14 +82,14 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth);
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
-void BLF_boundbox(int fontid, const char *str, struct rctf *box);
+void BLF_boundbox(int fontid, const char *str, size_t len, struct rctf *box);
/* The next both function return the width and height
* of the string, using the current font and both value
* are multiplied by the aspect of the font.
*/
-float BLF_width(int fontid, const char *str);
-float BLF_height(int fontid, const char *str);
+float BLF_width(int fontid, const char *str, size_t len);
+float BLF_height(int fontid, const char *str, size_t len);
/* Return dimensions of the font without any sample text. */
float BLF_height_max(int fontid);
@@ -100,7 +100,7 @@ float BLF_ascender(int fontid);
/* The following function return the width and height of the string, but
* just in one call, so avoid extra freetype2 stuff.
*/
-void BLF_width_and_height(int fontid, const char *str, float *width, float *height);
+void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height);
/* For fixed width fonts only, returns the width of a
* character.
@@ -111,9 +111,9 @@ float BLF_fixed_width(int fontid);
* of the string, using the default font and both value
* are multiplied by the aspect of the font.
*/
-void BLF_width_and_height_default(const char *str, float *width, float *height);
-float BLF_width_default(const char *str);
-float BLF_height_default(const char *str);
+void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height);
+float BLF_width_default(const char *str, size_t len);
+float BLF_height_default(const char *str, size_t len);
/* Set rotation for default font. */
void BLF_rotation_default(float angle);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 130eaaecba5..746ee3c0d93 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -592,44 +592,44 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
return columns;
}
-void BLF_boundbox(int fontid, const char *str, rctf *box)
+void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
{
FontBLF *font = blf_get(fontid);
if (font) {
- blf_font_boundbox(font, str, box);
+ blf_font_boundbox(font, str, len, box);
}
}
-void BLF_width_and_height(int fontid, const char *str, float *width, float *height)
+void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- blf_font_width_and_height(font, str, width, height);
+ blf_font_width_and_height(font, str, len, r_width, r_height);
}
else {
- *width = *height = 0.0f;
+ *r_width = *r_height = 0.0f;
}
}
-void BLF_width_and_height_default(const char *str, float *width, float *height)
+void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
{
if (!blf_global_font_init()) {
- *width = *height = 0.0f;
+ *r_width = *r_height = 0.0f;
return;
}
BLF_size(global_font_default, global_font_points, global_font_dpi);
- BLF_width_and_height(global_font_default, str, width, height);
+ BLF_width_and_height(global_font_default, str, len, r_width, r_height);
}
-float BLF_width(int fontid, const char *str)
+float BLF_width(int fontid, const char *str, size_t len)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- return blf_font_width(font, str);
+ return blf_font_width(font, str, len);
}
return 0.0f;
@@ -646,21 +646,21 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
-float BLF_width_default(const char *str)
+float BLF_width_default(const char *str, size_t len)
{
if (!blf_global_font_init())
return 0.0f;
BLF_size(global_font_default, global_font_points, global_font_dpi);
- return BLF_width(global_font_default, str);
+ return BLF_width(global_font_default, str, len);
}
-float BLF_height(int fontid, const char *str)
+float BLF_height(int fontid, const char *str, size_t len)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- return blf_font_height(font, str);
+ return blf_font_height(font, str, len);
}
return 0.0f;
@@ -710,14 +710,14 @@ float BLF_ascender(int fontid)
return 0.0f;
}
-float BLF_height_default(const char *str)
+float BLF_height_default(const char *str, size_t len)
{
if (!blf_global_font_init())
return 0.0f;
BLF_size(global_font_default, global_font_points, global_font_dpi);
- return BLF_height(global_font_default, str);
+ return BLF_height(global_font_default, str, len);
}
void BLF_rotation(int fontid, float angle)
diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c
index 721e86fbf21..da4d0b77a73 100644
--- a/source/blender/blenfont/intern/blf_dir.c
+++ b/source/blender/blenfont/intern/blf_dir.c
@@ -199,14 +199,14 @@ char *blf_dir_metrics_search(const char *filename)
s[2] = 'm';
/* first check .afm */
- if (BLI_exists(s))
- return s;
+ if (BLI_exists(mfile))
+ return mfile;
/* and now check .pfm */
s[0] = 'p';
- if (BLI_exists(s))
- return s;
+ if (BLI_exists(mfile))
+ return mfile;
}
MEM_freeN(mfile);
return NULL;
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 998b415a6af..40943225223 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -415,7 +415,7 @@ void blf_font_buffer(FontBLF *font, const char *str)
}
}
-void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
+void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
@@ -435,7 +435,7 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
blf_font_ensure_ascii_table(font);
- while (str[i]) {
+ while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (c == BLI_UTF8_ERR)
@@ -468,7 +468,7 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
}
}
-void blf_font_width_and_height(FontBLF *font, const char *str, float *width, float *height)
+void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float *width, float *height)
{
float xa, ya;
rctf box;
@@ -482,12 +482,12 @@ void blf_font_width_and_height(FontBLF *font, const char *str, float *width, flo
ya = 1.0f;
}
- blf_font_boundbox(font, str, &box);
+ blf_font_boundbox(font, str, len, &box);
*width = (BLI_rctf_size_x(&box) * xa);
*height = (BLI_rctf_size_y(&box) * ya);
}
-float blf_font_width(FontBLF *font, const char *str)
+float blf_font_width(FontBLF *font, const char *str, size_t len)
{
float xa;
rctf box;
@@ -497,11 +497,11 @@ float blf_font_width(FontBLF *font, const char *str)
else
xa = 1.0f;
- blf_font_boundbox(font, str, &box);
+ blf_font_boundbox(font, str, len, &box);
return BLI_rctf_size_x(&box) * xa;
}
-float blf_font_height(FontBLF *font, const char *str)
+float blf_font_height(FontBLF *font, const char *str, size_t len)
{
float ya;
rctf box;
@@ -511,7 +511,7 @@ float blf_font_height(FontBLF *font, const char *str)
else
ya = 1.0f;
- blf_font_boundbox(font, str, &box);
+ blf_font_boundbox(font, str, len, &box);
return BLI_rctf_size_y(&box) * ya;
}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 7d4b39dd337..9f6bad9b00d 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -55,10 +55,10 @@ void blf_font_draw(struct FontBLF *font, const char *str, size_t len);
void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
void blf_font_buffer(struct FontBLF *font, const char *str);
-void blf_font_boundbox(struct FontBLF *font, const char *str, struct rctf *box);
-void blf_font_width_and_height(struct FontBLF *font, const char *str, float *width, float *height);
-float blf_font_width(struct FontBLF *font, const char *str);
-float blf_font_height(struct FontBLF *font, const char *str);
+void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *box);
+void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *width, float *height);
+float blf_font_width(struct FontBLF *font, const char *str, size_t len);
+float blf_font_height(struct FontBLF *font, const char *str, size_t len);
float blf_font_fixed_width(struct FontBLF *font);
void blf_font_free(struct FontBLF *font);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index f2d9c0efc13..a240e79e473 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 269
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 7
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index dee27cebf59..8b2107071d3 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -76,7 +76,7 @@ struct BoundBox *BKE_curve_boundbox_get(struct Object *ob);
void BKE_curve_texspace_calc(struct Curve *cu);
void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], float r_size[3]);
-bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
+bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]);
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
@@ -122,7 +122,7 @@ struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
void BKE_nurb_test2D(struct Nurb *nu);
-void BKE_nurb_minmax(struct Nurb *nu, float min[3], float max[3]);
+void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3]);
void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride);
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3cb20ead39e..86c111653d1 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -38,7 +38,7 @@ struct bGPDframe;
/* ------------ Grease-Pencil API ------------------ */
-void free_gpencil_strokes(struct bGPDframe *gpf);
+bool free_gpencil_strokes(struct bGPDframe *gpf);
void free_gpencil_frames(struct bGPDlayer *gpl);
void free_gpencil_layers(struct ListBase *list);
void BKE_gpencil_free(struct bGPdata *gpd);
@@ -59,7 +59,7 @@ void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gp
struct bGPDframe *BKE_gpencil_layer_find_frame(struct bGPDlayer *gpl, int cframe);
struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, short addnew);
-void gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
+bool gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
struct bGPDlayer *gpencil_layer_getactive(struct bGPdata *gpd);
void gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
void gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index ba33da7729c..7806c4a94a1 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -89,6 +89,10 @@ void BKE_lattice_translate(struct Lattice *lt, float offset[3], int do_keys);
int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w);
void BKE_lattice_index_to_uvw(struct Lattice *lt, const int index, int *r_u, int *r_v, int *r_w);
+int BKE_lattice_index_flip(struct Lattice *lt, const int index,
+ const bool flip_u, const bool flip_v, const bool flip_w);
+void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, const short flag,
+ const bool clear, const bool respecthide);
#endif
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b700cbb16db..28a4a30fa91 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -306,6 +306,8 @@ typedef struct bNodeTreeType {
void (*update)(struct bNodeTree *ntree);
int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
+
+ void (*node_add_init)(struct bNodeTree *ntree, struct bNode *bnode);
/* RNA integration */
ExtensionRNA ext;
@@ -413,8 +415,8 @@ void nodeRegisterSocketType(struct bNodeSocketType *stype);
void nodeUnregisterSocketType(struct bNodeSocketType *stype);
bool nodeSocketIsRegistered(struct bNodeSocket *sock);
struct GHashIterator *nodeSocketTypeGetIterator(void);
-const char * nodeStaticSocketType(int type, int subtype);
-const char * nodeStaticSocketInterfaceType(int type, int subtype);
+const char *nodeStaticSocketType(int type, int subtype);
+const char *nodeStaticSocketInterfaceType(int type, int subtype);
/* helper macros for iterating over node types */
#define NODE_SOCKET_TYPES_BEGIN(stype) \
@@ -476,7 +478,7 @@ void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
-int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
+bool nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
@@ -740,6 +742,7 @@ struct ShadeResult;
#define SH_NODE_SEPHSV 183
#define SH_NODE_COMBHSV 184
#define SH_NODE_BSDF_HAIR 185
+#define SH_NODE_LAMP 186
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 3c0928d38a0..9702b2ee30f 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -282,6 +282,8 @@ struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
void BKE_screen_view3d_scene_sync(struct bScreen *sc);
void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
+void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
+void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
/* zoom factor conversion */
float BKE_screen_view3d_zoom_to_fac(float camzoom);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 0ac3737b6a2..437956f2297 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -41,7 +41,6 @@ set(INC
../../../intern/iksolver/extern
../../../intern/memutil
../../../intern/mikktspace
- ../../../intern/opennl/extern
../../../intern/raskter
../../../intern/smoke/extern
../../../extern/libmv
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 07dbc1d6065..5e5dea1c163 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -50,7 +50,6 @@ incs = [
'#/intern/bsp/extern',
'#/intern/elbeem/extern',
'#/intern/iksolver/extern',
- '#/intern/opennl/extern',
'#/intern/smoke/extern',
'#/intern/atomic',
'../avi',
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 731196c2480..5c98fe48ea6 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -3315,7 +3315,7 @@ bool DM_is_valid(DerivedMesh *dm)
const bool do_fixes = false;
bool is_valid = true;
- bool is_change = true;
+ bool changed = true;
is_valid &= BKE_mesh_validate_all_customdata(
dm->getVertDataLayout(dm),
@@ -3323,7 +3323,7 @@ bool DM_is_valid(DerivedMesh *dm)
dm->getLoopDataLayout(dm),
dm->getPolyDataLayout(dm),
0, /* setting mask here isn't useful, gives false positives */
- do_verbose, do_fixes, &is_change);
+ do_verbose, do_fixes, &changed);
is_valid &= BKE_mesh_validate_arrays(
NULL,
@@ -3333,9 +3333,9 @@ bool DM_is_valid(DerivedMesh *dm)
dm->getLoopArray(dm), dm->getNumLoops(dm),
dm->getPolyArray(dm), dm->getNumPolys(dm),
dm->getVertDataArray(dm, CD_MDEFORMVERT),
- do_verbose, do_fixes, &is_change);
+ do_verbose, do_fixes, &changed);
- BLI_assert(is_change == false);
+ BLI_assert(changed == false);
return is_valid;
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 3be80a7e30d..0267c9a6122 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -335,15 +335,15 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
* - otherwise, just append to end
*/
if (extension[0]) {
- int change = 1;
+ bool changed = true;
- while (change) { /* remove extensions */
- change = 0;
+ while (changed) { /* remove extensions */
+ changed = false;
if (len > 2 && basename[len - 2] == '.') {
if (basename[len - 1] == 'L' || basename[len - 1] == 'R') { /* L R */
basename[len - 2] = '\0';
len -= 2;
- change = 1;
+ changed = true;
}
}
else if (len > 3 && basename[len - 3] == '.') {
@@ -352,7 +352,7 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
{
basename[len - 3] = '\0';
len -= 3;
- change = 1;
+ changed = true;
}
}
else if (len > 4 && basename[len - 4] == '.') {
@@ -361,7 +361,7 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
{
basename[len - 4] = '\0';
len -= 4;
- change = 1;
+ changed = true;
}
}
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 5ef39e8d48e..96adadebb48 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -897,6 +897,12 @@ int BKE_copybuffer_save(const char *filename, ReportList *reports)
ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
int a, retval;
+ /* path backup/restore */
+ void *path_list_backup;
+ const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
+
+ path_list_backup = BKE_bpath_list_backup(G.main, path_list_flag);
+
BLO_main_expander(copybuffer_doit);
BLO_expand_main(NULL, G.main);
@@ -918,7 +924,7 @@ int BKE_copybuffer_save(const char *filename, ReportList *reports)
/* save the buffer */
- retval = BLO_write_file(mainb, filename, 0, reports, NULL);
+ retval = BLO_write_file(mainb, filename, G_FILE_RELATIVE_REMAP, reports, NULL);
/* move back the main, now sorted again */
set_listbasepointers(G.main, lbarray);
@@ -938,6 +944,11 @@ int BKE_copybuffer_save(const char *filename, ReportList *reports)
/* set id flag to zero; */
flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0);
+ if (path_list_backup) {
+ BKE_bpath_list_restore(G.main, path_list_flag, path_list_backup);
+ BKE_bpath_list_free(path_list_backup);
+ }
+
return retval;
}
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index 732c0c35feb..79b3f89da20 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -68,13 +68,10 @@ void printfGlyph(bmGlyph *glyph)
printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
}
-#define MAX2(x, y) ((x) > (y) ? (x) : (y))
-#define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z)))
-
void calcAlpha(ImBuf *ibuf)
{
int i;
- char * rect;
+ char *rect;
if (ibuf) {
rect = (char *) ibuf->rect;
@@ -88,7 +85,7 @@ void calcAlpha(ImBuf *ibuf)
void readBitmapFontVersion0(ImBuf *ibuf, unsigned char *rect, int step)
{
int glyphcount, bytes, i, index, linelength, ysize;
- unsigned char * buffer;
+ unsigned char *buffer;
bmFont * bmfont;
linelength = ibuf->x * step;
@@ -174,7 +171,7 @@ void readBitmapFontVersion0(ImBuf *ibuf, unsigned char *rect, int step)
void detectBitmapFont(ImBuf *ibuf)
{
- unsigned char * rect;
+ unsigned char *rect;
unsigned short version;
int i;
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 33c6f3eb7c0..8a59aab4036 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -45,6 +45,7 @@
#include "BKE_texture.h"
#include "BKE_icons.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -306,7 +307,7 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST_FLAG(BRUSH_ADAPTIVE_SPACE);
BR_TEST_FLAG(BRUSH_LOCK_SIZE);
BR_TEST_FLAG(BRUSH_EDGE_TO_EDGE);
- BR_TEST_FLAG(BRUSH_RESTORE_MESH);
+ 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);
@@ -639,6 +640,16 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
rgba[2] = intensity;
rgba[3] = 1.0f;
}
+ else {
+ if (br->mtex.tex->type == TEX_IMAGE && br->mtex.tex->ima) {
+ ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(br->mtex.tex->ima, &br->mtex.tex->iuser, pool);
+ /* For consistency, sampling always returns color in linear space */
+ if (tex_ibuf->rect_float == NULL) {
+ IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, tex_ibuf->rect_colorspace);
+ }
+ BKE_image_pool_release_ibuf(br->mtex.tex->ima, tex_ibuf, pool);
+ }
+ }
return intensity;
}
@@ -899,7 +910,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
/* jitter-ed brush gives weird and unpredictable result for this
* kinds of stroke, so manually disable jitter usage (sergey) */
- use_jitter &= (brush->flag & (BRUSH_RESTORE_MESH | BRUSH_ANCHORED)) == 0;
+ use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
if (use_jitter) {
float rand_pos[2];
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 536ec95e3d1..aee8ede4062 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -227,7 +227,7 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob)
else if (ob->type == OB_LAMP) {
/* lamp object */
Lamp *la = ob->data;
- float fac = cosf((float)M_PI * la->spotsize / 360.0f);
+ float fac = cosf(la->spotsize * 0.5f);
float phi = acos(fac);
params->lens = 16.0f * fac / sinf(phi);
@@ -535,16 +535,11 @@ int BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
float plane_isect_pt_1[3], plane_isect_pt_2[3];
- /* could make a generic macro */
-#define SQRT_SIGNED(f) copysign(sqrtf(fabsf(f)), f)
-
/* 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], SQRT_SIGNED(data_cb.dist_vals_sq[i]));
+ mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], sqrtf_signed(data_cb.dist_vals_sq[i]));
}
-#undef SQRT_SIGNED
-
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]);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index bcf0eafaa65..969db19a256 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -143,7 +143,6 @@ void BKE_curve_editNurb_free(Curve *cu)
void BKE_curve_free(Curve *cu)
{
BKE_nurbList_free(&cu->nurb);
- BKE_displist_free(&cu->disp);
BKE_curve_editfont_free(cu);
BKE_curve_editNurb_free(cu);
@@ -223,8 +222,6 @@ Curve *BKE_curve_copy(Curve *cu)
cun->key = BKE_key_copy(cu->key);
if (cun->key) cun->key->from = (ID *)cun;
- cun->disp.first = cun->disp.last = NULL;
-
cun->editnurb = NULL;
cun->editfont = NULL;
cun->selboxes = NULL;
@@ -379,7 +376,11 @@ void BKE_curve_boundbox_calc(Curve *cu, float r_loc[3], float r_size[3])
if (!r_size) r_size = msize;
INIT_MINMAX(min, max);
- BKE_displist_minmax(&cu->disp, min, max);
+ if (!BKE_curve_minmax(cu, true, min, max)) {
+ min[0] = min[1] = min[2] = -1.0f;
+ max[0] = max[1] = max[2] = 1.0f;
+ }
+
mid_v3_v3v3(r_loc, min, max);
r_size[0] = (max[0] - min[0]) / 2.0f;
@@ -642,18 +643,34 @@ void BKE_nurb_test2D(Nurb *nu)
}
}
-void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
+/* if use_radius is truth, minmax will take points' radius into account,
+ * which will make boundbox closer to bevelled curve.
+ */
+void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3])
{
BezTriple *bezt;
BPoint *bp;
int a;
+ float point[3];
if (nu->type == CU_BEZIER) {
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
+ if (use_radius) {
+ float radius_vector[3];
+ radius_vector[0] = radius_vector[1] = radius_vector[2] = bezt->radius;
+
+ add_v3_v3v3(point, bezt->vec[1], radius_vector);
+ minmax_v3v3_v3(min, max, point);
+
+ sub_v3_v3v3(point, bezt->vec[1], radius_vector);
+ minmax_v3v3_v3(min, max, point);
+ }
+ else {
+ minmax_v3v3_v3(min, max, bezt->vec[1]);
+ }
minmax_v3v3_v3(min, max, bezt->vec[0]);
- minmax_v3v3_v3(min, max, bezt->vec[1]);
minmax_v3v3_v3(min, max, bezt->vec[2]);
bezt++;
}
@@ -662,7 +679,20 @@ void BKE_nurb_minmax(Nurb *nu, float min[3], float max[3])
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- minmax_v3v3_v3(min, max, bp->vec);
+ if (nu->pntsv == 1 && use_radius) {
+ float radius_vector[3];
+ radius_vector[0] = radius_vector[1] = radius_vector[2] = bp->radius;
+
+ add_v3_v3v3(point, bp->vec, radius_vector);
+ minmax_v3v3_v3(min, max, point);
+
+ sub_v3_v3v3(point, bp->vec, radius_vector);
+ minmax_v3v3_v3(min, max, point);
+ }
+ else {
+ /* Surfaces doesn't use bevel, so no need to take radius into account. */
+ minmax_v3v3_v3(min, max, bp->vec);
+ }
bp++;
}
}
@@ -1518,6 +1548,9 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
else
numVerts += dl->parts * (dl->nr + 1);
}
+ else if (dl->flag & DL_CYCL_V) {
+ numVerts += (dl->parts + 1) * dl->nr;
+ }
else
numVerts += dl->parts * dl->nr;
}
@@ -1553,6 +1586,9 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
if (dl->flag & DL_CYCL_V)
sizev++;
}
+ else if (dl->flag & DL_CYCL_V) {
+ sizev++;
+ }
for (u = 0; u < sizev; u++) {
for (v = 0; v < sizeu; v++, fp += 3) {
@@ -3658,30 +3694,30 @@ bool BKE_nurb_check_valid_v(struct Nurb *nu)
bool BKE_nurb_order_clamp_u(struct Nurb *nu)
{
- bool change = false;
+ bool changed = false;
if (nu->pntsu < nu->orderu) {
nu->orderu = nu->pntsu;
- change = true;
+ changed = true;
}
if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
CLAMP(nu->orderu, 3, 4);
- change = true;
+ changed = true;
}
- return change;
+ return changed;
}
bool BKE_nurb_order_clamp_v(struct Nurb *nu)
{
- bool change = false;
+ bool changed = false;
if (nu->pntsv < nu->orderv) {
nu->orderv = nu->pntsv;
- change = true;
+ changed = true;
}
if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
CLAMP(nu->orderv, 3, 4);
- change = true;
+ changed = true;
}
- return change;
+ return changed;
}
bool BKE_nurb_type_convert(Nurb *nu, const short type, const bool use_handles)
@@ -3834,13 +3870,13 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
/* basic vertex data functions */
-bool BKE_curve_minmax(Curve *cu, float min[3], float max[3])
+bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
for (nu = nurb_lb->first; nu; nu = nu->next)
- BKE_nurb_minmax(nu, min, max);
+ BKE_nurb_minmax(nu, use_radius, min, max);
return (nurb_lb->first != NULL);
}
@@ -3887,7 +3923,7 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3])
{
float min[3], max[3];
INIT_MINMAX(min, max);
- if (BKE_curve_minmax(cu, min, max)) {
+ if (BKE_curve_minmax(cu, false, min, max)) {
mid_v3_v3v3(cent, min, max);
return true;
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 8a74f4719d5..441a2b410ad 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -507,16 +507,15 @@ static void layerCopy_mdisps(const void *source, void *dest, int count)
if (s[i].disps) {
d[i].disps = MEM_dupallocN(s[i].disps);
d[i].hidden = MEM_dupallocN(s[i].hidden);
- d[i].totdisp = s[i].totdisp;
- d[i].level = s[i].level;
}
else {
d[i].disps = NULL;
d[i].hidden = NULL;
- d[i].totdisp = 0;
- d[i].level = 0;
}
-
+
+ /* still copy even if not in memory, displacement can be external */
+ d[i].totdisp = s[i].totdisp;
+ d[i].level = s[i].level;
}
}
@@ -1296,7 +1295,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataLayer *layer, *newlayer;
void *data;
int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0;
- bool change = false;
+ bool changed = false;
for (i = 0; i < source->totlayer; ++i) {
layer = &source->layers[i];
@@ -1346,12 +1345,12 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
- change = true;
+ changed = true;
}
}
CustomData_update_typemap(dest);
- return change;
+ return changed;
}
void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
@@ -1752,6 +1751,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
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;
@@ -1768,7 +1768,7 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
if (i != -1) {
/* don't decrement zero index */
- const int index_nonzero = index ? index : 1;
+ const int index_nonzero = n ? n : 1;
CustomDataLayer *layer;
for (layer = &data->layers[i]; i < data->totlayer && layer->type == type; i++, layer++) {
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index cb7b4a32feb..6ef20ecc047 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1466,7 +1466,8 @@ static void flush_update_node(Main *bmain, DagNode *node, unsigned int layer, in
{
DagAdjList *itA;
Object *ob, *obc;
- int oldflag, changed = 0;
+ int oldflag;
+ bool changed = false;
unsigned int all_layer;
node->lasttime = curtime;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 6a89ca2cb84..dd1df6ef4b0 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1086,7 +1086,7 @@ static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
return dm;
}
-static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
{
float (*orco)[3], (*layerorco)[3];
int totvert, a;
@@ -1094,23 +1094,12 @@ static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *
totvert = dm->getNumVerts(dm);
- if (orcodm) {
- orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
+ orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
- if (orcodm->getNumVerts(orcodm) == totvert)
- orcodm->getVertCos(orcodm, orco);
- else
- dm->getVertCos(dm, orco);
- }
- else {
- int totvert_curve;
- orco = (float(*)[3])BKE_curve_make_orco(scene, ob, &totvert_curve);
- if (totvert != totvert_curve) {
- MEM_freeN(orco);
- orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
- dm->getVertCos(dm, orco);
- }
- }
+ if (orcodm->getNumVerts(orcodm) == totvert)
+ orcodm->getVertCos(orcodm, orco);
+ else
+ dm->getVertCos(dm, orco);
for (a = 0; a < totvert; a++) {
float *co = orco[a];
@@ -1157,6 +1146,15 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
md = pretessellatePoint->next;
}
+ /* If modifiers are disabled, we wouldn't be here because
+ * this function is only called if there're enabled constructive
+ * modifiers applied on the curve.
+ *
+ * This means we can create ORCO DM in advance and assume it's
+ * never NULL.
+ */
+ orcodm = create_orco_dm(scene, ob);
+
for (; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1167,9 +1165,6 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
if (mti->type != eModifierTypeType_Constructive)
continue;
- if (!orcodm)
- orcodm = create_orco_dm(scene, ob);
-
ndm = modwrap_applyModifier(md, ob, orcodm, app_flag);
if (ndm) {
@@ -1182,10 +1177,9 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
}
/* add an orco layer if needed */
- add_orco_dm(scene, ob, derivedFinal, orcodm);
+ add_orco_dm(ob, derivedFinal, orcodm);
- if (orcodm)
- orcodm->release(orcodm);
+ orcodm->release(orcodm);
}
void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1271,11 +1265,6 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
}
}
- /* make copy of 'undeformed" displist for texture space calculation
- * actually, it's not totally undeformed -- pre-tessellation modifiers are
- * already applied, thats how it worked for years, so keep for compatibility (sergey) */
- BKE_displist_copy(&cu->disp, dispbase);
-
if (!forOrco) {
curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal,
forRender, renderResolution);
@@ -1575,11 +1564,6 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if ((cu->flag & CU_PATH) && !forOrco)
calc_curvepath(ob, &nubase);
- /* make copy of 'undeformed" displist for texture space calculation
- * actually, it's not totally undeformed -- pre-tessellation modifiers are
- * already applied, thats how it worked for years, so keep for compatibility (sergey) */
- BKE_displist_copy(&cu->disp, dispbase);
-
if (!forOrco)
curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, forRender, renderResolution);
@@ -1593,7 +1577,6 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
{
- Curve *cu = ob->data;
ListBase *dispbase;
/* The same check for duplis as in do_makeDispListCurveTypes.
@@ -1602,7 +1585,6 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
return;
- BKE_displist_free(&cu->disp);
BKE_object_free_derived_caches(ob);
if (!ob->curve_cache) {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index a40d7401566..32098c67ca7 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1148,6 +1148,10 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
/* stop here... */
return 0.0f;
}
+ else {
+ dtar1->flag &= ~DTAR_FLAG_INVALID;
+ dtar2->flag &= ~DTAR_FLAG_INVALID;
+ }
/* use the final posed locations */
mat4_to_quat(q1, pchan->pose_mat);
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index d87c93310c8..3e0668ba05c 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -83,7 +83,6 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con
FreestyleModuleConfig *module, *new_module;
new_config->mode = config->mode;
- new_config->raycasting_algorithm = config->raycasting_algorithm; /* deprecated */
new_config->flags = config->flags;
new_config->sphere_radius = config->sphere_radius;
new_config->dkr_epsilon = config->dkr_epsilon;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 42e146301a2..232ee335fbb 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -58,13 +58,11 @@
/* --------- Memory Management ------------ */
/* Free strokes belonging to a gp-frame */
-void free_gpencil_strokes(bGPDframe *gpf)
+bool free_gpencil_strokes(bGPDframe *gpf)
{
bGPDstroke *gps, *gpsn;
-
- /* error checking */
- if (gpf == NULL) return;
-
+ bool changed = (gpf->strokes.first != NULL);
+
/* free strokes */
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;
@@ -73,6 +71,8 @@ void free_gpencil_strokes(bGPDframe *gpf)
if (gps->points) MEM_freeN(gps->points);
BLI_freelinkN(&gpf->strokes, gps);
}
+
+ return changed;
}
/* Free all of a gp-layer's frames */
@@ -467,16 +467,20 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
}
/* delete the given frame from a layer */
-void gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
+bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
{
+ bool changed = false;
+
/* error checking */
if (ELEM(NULL, gpl, gpf))
- return;
+ return false;
/* free the frame and its data */
- free_gpencil_strokes(gpf);
+ changed = free_gpencil_strokes(gpf);
BLI_freelinkN(&gpl->frames, gpf);
gpl->actframe = NULL;
+
+ return changed;
}
/* get the active gp-layer for editing */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 6a411f8c308..d59a23c1c30 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -976,7 +976,7 @@ int BKE_imtype_to_ftype(const char imtype)
return RADHDR;
#endif
else if (imtype == R_IMF_IMTYPE_PNG)
- return PNG | 90;
+ return PNG | 15;
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS)
return DDS;
@@ -1340,7 +1340,7 @@ void BKE_imformat_defaults(ImageFormatData *im_format)
im_format->imtype = R_IMF_IMTYPE_PNG;
im_format->depth = R_IMF_CHAN_DEPTH_8;
im_format->quality = 90;
- im_format->compress = 90;
+ im_format->compress = 15;
BKE_color_managed_display_settings_init(&im_format->display_settings);
BKE_color_managed_view_settings_init(&im_format->view_settings);
@@ -1636,6 +1636,9 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* this could be an argument if we want to operate on non linear float imbuf's
* for now though this is only used for renders which use scene settings */
+#define TEXT_SIZE_CHECK(str, w, h) \
+ ((str[0]) && ((void)(h = h_fixed), (w = BLF_width(mono, str, sizeof(str)))))
+
#define BUFF_MARGIN_X 2
#define BUFF_MARGIN_Y 1
@@ -1665,9 +1668,8 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x = 0;
y = height;
- if (stamp_data.file[0]) {
+ if (TEXT_SIZE_CHECK(stamp_data.file, w, h)) {
/* Top left corner */
- BLF_width_and_height(mono, stamp_data.file, &w, &h); h = h_fixed;
y -= h;
/* also a little of space to the background. */
@@ -1683,8 +1685,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
}
/* Top left corner, below File */
- if (stamp_data.note[0]) {
- BLF_width_and_height(mono, stamp_data.note, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.note, w, h)) {
y -= h;
/* and space for background. */
@@ -1699,8 +1700,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
}
/* Top left corner, below File (or Note) */
- if (stamp_data.date[0]) {
- BLF_width_and_height(mono, stamp_data.date, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
y -= h;
/* and space for background. */
@@ -1715,8 +1715,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
}
/* Top left corner, below File, Date or Note */
- if (stamp_data.rendertime[0]) {
- BLF_width_and_height(mono, stamp_data.rendertime, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
y -= h;
/* and space for background. */
@@ -1731,8 +1730,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y = 0;
/* Bottom left corner, leaving space for timing */
- if (stamp_data.marker[0]) {
- BLF_width_and_height(mono, stamp_data.marker, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.marker, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
@@ -1747,8 +1745,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
}
/* Left bottom corner */
- if (stamp_data.time[0]) {
- BLF_width_and_height(mono, stamp_data.time, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.time, w, h)) {
/* extra space for background */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
@@ -1762,8 +1759,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x += w + pad;
}
- if (stamp_data.frame[0]) {
- BLF_width_and_height(mono, stamp_data.frame, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.frame, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
@@ -1777,8 +1773,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x += w + pad;
}
- if (stamp_data.camera[0]) {
- BLF_width_and_height(mono, stamp_data.camera, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.camera, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
@@ -1790,8 +1785,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x += w + pad;
}
- if (stamp_data.cameralens[0]) {
- BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.cameralens, w, h)) {
/* extra space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
@@ -1800,8 +1794,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_draw_buffer(mono, stamp_data.cameralens);
}
- if (stamp_data.scene[0]) {
- BLF_width_and_height(mono, stamp_data.scene, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
/* Bottom right corner, with an extra space because blenfont is too strict! */
x = width - w - 2;
@@ -1815,8 +1808,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_draw_buffer(mono, stamp_data.scene);
}
- if (stamp_data.strip[0]) {
- BLF_width_and_height(mono, stamp_data.strip, &w, &h); h = h_fixed;
+ if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
/* Top right corner, with an extra space because blenfont is too strict! */
x = width - w - pad;
@@ -1833,6 +1825,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* cleanup the buffer. */
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+#undef TEXT_SIZE_CHECK
#undef BUFF_MARGIN_X
#undef BUFF_MARGIN_Y
}
@@ -2855,7 +2848,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
return ibuf;
}
-static void image_get_fame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
+static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
{
int frame = 0, index = 0;
@@ -3176,7 +3169,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
return BKE_image_acquire_ibuf(ima, iuser, NULL);
}
- image_get_fame_and_index(ima, iuser, &frame, &index);
+ image_get_frame_and_index(ima, iuser, &frame, &index);
ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
if (found)
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index c8e18bc3dee..fce6ed9d6c6 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1265,7 +1265,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
k = clmd->sim_parms->structural;
- scaling = k + s->stiffness * ABS(clmd->sim_parms->max_struct-k);
+ scaling = k + s->stiffness * fabsf(clmd->sim_parms->max_struct - k);
k = scaling / (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
@@ -1305,7 +1305,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
k = clmd->sim_parms->goalspring;
- scaling = k + s->stiffness * ABS(clmd->sim_parms->max_struct-k);
+ scaling = k + s->stiffness * fabsf(clmd->sim_parms->max_struct - k);
k = verts [s->ij].goal * scaling / (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
@@ -1324,7 +1324,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
k = clmd->sim_parms->bending;
- scaling = k + s->stiffness * ABS(clmd->sim_parms->max_bend-k);
+ scaling = k + s->stiffness * fabsf(clmd->sim_parms->max_bend - k);
cb = k = scaling / (20.0f * (clmd->sim_parms->avg_spring_len + FLT_EPSILON));
mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb));
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 903b032e080..904dbec24a4 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -63,14 +63,13 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
la->r = la->g = la->b = la->k = 1.0f;
la->haint = la->energy = 1.0f;
la->dist = 25.0f;
- la->spotsize = 45.0f;
+ la->spotsize = DEG2RADF(45.0f);
la->spotblend = 0.15f;
la->att2 = 1.0f;
la->mode = LA_SHAD_BUF;
la->bufsize = 512;
la->clipsta = 0.5f;
la->clipend = 40.0f;
- la->shadspotsize = 45.0f;
la->samp = 3;
la->bias = 1.0f;
la->soft = 3.0f;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 60b4db6aa9b..850636e986c 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -36,9 +36,10 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -63,7 +64,7 @@
#include "BKE_deform.h"
-int BKE_lattice_index_from_uvw(struct Lattice *lt,
+int BKE_lattice_index_from_uvw(Lattice *lt,
const int u, const int v, const int w)
{
const int totu = lt->pntsu;
@@ -72,7 +73,7 @@ int BKE_lattice_index_from_uvw(struct Lattice *lt,
return (w * (totu * totv) + (v * totu) + u);
}
-void BKE_lattice_index_to_uvw(struct Lattice *lt, const int index,
+void BKE_lattice_index_to_uvw(Lattice *lt, const int index,
int *r_u, int *r_v, int *r_w)
{
const int totu = lt->pntsu;
@@ -83,6 +84,49 @@ void BKE_lattice_index_to_uvw(struct Lattice *lt, const int index,
*r_w = (index / (totu * totv));
}
+int BKE_lattice_index_flip(Lattice *lt, const int index,
+ const bool flip_u, const bool flip_v, const bool flip_w)
+{
+ int u, v, w;
+
+ BKE_lattice_index_to_uvw(lt, index, &u, &v, &w);
+
+ if (flip_u) {
+ u = (lt->pntsu - 1) - u;
+ }
+
+ if (flip_v) {
+ v = (lt->pntsv - 1) - v;
+ }
+
+ if (flip_w) {
+ w = (lt->pntsw - 1) - w;
+ }
+
+ return BKE_lattice_index_from_uvw(lt, u, v, w);
+}
+
+void BKE_lattice_bitmap_from_flag(Lattice *lt, BLI_bitmap *bitmap, const short flag,
+ const bool clear, const bool respecthide)
+{
+ const unsigned int tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ unsigned int i;
+ BPoint *bp;
+
+ bp = lt->def;
+ for (i = 0; i < tot; i++, bp++) {
+ if ((bp->f1 & flag) && (!respecthide || !bp->hide)) {
+ BLI_BITMAP_SET(bitmap, i);
+ }
+ else {
+ if (clear) {
+ BLI_BITMAP_CLEAR(bitmap, i);
+ }
+ }
+ }
+
+}
+
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du)
{
if (res == 1) {
@@ -1072,7 +1116,7 @@ struct BPoint *BKE_lattice_active_point_get(Lattice *lt)
}
}
-void BKE_lattice_center_median(struct Lattice *lt, float cent[3])
+void BKE_lattice_center_median(Lattice *lt, float cent[3])
{
int i, numVerts;
@@ -1087,7 +1131,7 @@ void BKE_lattice_center_median(struct Lattice *lt, float cent[3])
mul_v3_fl(cent, 1.0f / (float)numVerts);
}
-void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3])
+void BKE_lattice_minmax(Lattice *lt, float min[3], float max[3])
{
int i, numVerts;
@@ -1098,7 +1142,7 @@ void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3])
minmax_v3v3_v3(min, max, lt->def[i].vec);
}
-void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3])
+void BKE_lattice_center_bounds(Lattice *lt, float cent[3])
{
float min[3], max[3];
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 83c257dbd56..1128c3e55c7 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -2375,7 +2375,7 @@ bool BKE_mball_minmax_ex(MetaBall *mb, float min[3], float max[3],
{
const float scale = obmat ? mat4_to_scale(obmat) : 1.0f;
MetaElem *ml;
- bool change = false;
+ bool changed = false;
float centroid[3], vec[3];
INIT_MINMAX(min, max);
@@ -2398,11 +2398,11 @@ bool BKE_mball_minmax_ex(MetaBall *mb, float min[3], float max[3],
add_v3_fl(vec, scale_mb * i);
minmax_v3v3_v3(min, max, vec);
}
- change = true;
+ changed = true;
}
}
- return change;
+ return changed;
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 844252c583c..af23a84a26b 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -251,7 +251,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) {
if (dw1->def_nr != dw2->def_nr)
return MESHCMP_DVERT_GROUPMISMATCH;
- if (ABS(dw1->weight - dw2->weight) > thresh)
+ if (fabsf(dw1->weight - dw2->weight) > thresh)
return MESHCMP_DVERT_WEIGHTMISMATCH;
}
}
@@ -1342,6 +1342,9 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
if (dl->flag & DL_CYCL_V)
orco_sizev++;
}
+ else if (dl->flag & DL_CYCL_V) {
+ orco_sizev++;
+ }
for (i = 0; i < 4; i++, mloopuv++) {
/* find uv based on vertex index into grid array */
@@ -1351,6 +1354,8 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu;
/* cyclic correction */
+ if ((i == 1 || i == 2) && mloopuv->uv[0] == 0.0f)
+ mloopuv->uv[0] = 1.0f;
if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f)
mloopuv->uv[1] = 1.0f;
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 1e74ce23c2c..0a85d2bfa06 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_bitmap.h"
-#include "BLI_scanfill.h"
+#include "BLI_polyfill2d.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_alloca.h"
@@ -1298,10 +1298,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
MPoly *mp, *mpoly;
MLoop *ml, *mloop;
MFace *mface, *mf;
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
- ScanFillFace *sf_tri;
- MemArena *sf_arena = NULL;
+ MemArena *arena = NULL;
int *mface_to_poly_map;
int lindex[4]; /* only ever use 3 in this case */
int poly_index, j, mface_index;
@@ -1375,60 +1372,60 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
}
#endif /* USE_TESSFACE_SPEEDUP */
else {
-#define USE_TESSFACE_CALCNORMAL
+ const float *co_curr, *co_prev;
- unsigned int totfilltri;
-
-#ifdef USE_TESSFACE_CALCNORMAL
float normal[3];
- zero_v3(normal);
-#endif
- ml = mloop + mp->loopstart;
- if (UNLIKELY(sf_arena == NULL)) {
- sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
- }
+ float axis_mat[3][3];
+ float (*projverts)[2];
+ unsigned int (*tris)[3];
- BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
- sf_vert_first = NULL;
- sf_vert_last = NULL;
- for (j = 0; j < mp->totloop; j++, ml++) {
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, mvert[ml->v].co);
+ const unsigned int loopstart = (unsigned int)mp->loopstart;
+ const int totfilltri = mp->totloop - 2;
- sf_vert->keyindex = (unsigned int)(mp->loopstart + j);
+ if (UNLIKELY(arena == NULL)) {
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
- if (sf_vert_last) {
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
-#ifdef USE_TESSFACE_CALCNORMAL
- add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert->co);
-#endif
- }
+ tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
+ projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp->totloop);
+
+ zero_v3(normal);
- if (!sf_vert_first)
- sf_vert_first = sf_vert;
- sf_vert_last = sf_vert;
+ /* calc normal */
+ ml = mloop + loopstart;
+ co_prev = mvert[ml[mp->totloop - 1].v].co;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ co_curr = mvert[ml->v].co;
+ add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
+ co_prev = co_curr;
}
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
-#ifdef USE_TESSFACE_CALCNORMAL
- add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert_first->co);
if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
normal[2] = 1.0f;
}
- totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, normal);
-#else
- totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
-#endif
- BLI_assert(totfilltri <= (unsigned int)(mp->totloop - 2));
- (void)totfilltri;
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
+ /* project verts to 2d */
+ axis_dominant_v3_to_m3(axis_mat, normal);
+
+ ml = mloop + loopstart;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
+ }
+
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, (unsigned int)mp->totloop, tris, arena);
+
+ /* apply fill */
+ ml = mloop + loopstart;
+ for (j = 0; j < totfilltri; j++) {
+ unsigned int *tri = tris[j];
+
mface_to_poly_map[mface_index] = poly_index;
mf = &mface[mface_index];
/* set loop indices, transformed to vert indices later */
- mf->v1 = sf_tri->v1->keyindex;
- mf->v2 = sf_tri->v2->keyindex;
- mf->v3 = sf_tri->v3->keyindex;
+ mf->v1 = loopstart + tri[0];
+ mf->v2 = loopstart + tri[1];
+ mf->v3 = loopstart + tri[2];
mf->v4 = 0;
mf->mat_nr = mp->mat_nr;
@@ -1441,15 +1438,13 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
mface_index++;
}
- BLI_scanfill_end_arena(&sf_ctx, sf_arena);
-
-#undef USE_TESSFACE_CALCNORMAL
+ BLI_memarena_clear(arena);
}
}
- if (sf_arena) {
- BLI_memarena_free(sf_arena);
- sf_arena = NULL;
+ if (arena) {
+ BLI_memarena_free(arena);
+ arena = NULL;
}
CustomData_free(fdata, totface);
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index a4f5529ee43..ad6a2de31cd 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -216,7 +216,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
MPoly *mpolys, unsigned int totpoly,
MDeformVert *dverts, /* assume totvert length */
const bool do_verbose, const bool do_fixes,
- bool *r_change)
+ bool *r_changed)
{
# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0
# define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)
@@ -854,7 +854,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_MSG("%s: finished\n\n", __func__);
- *r_change = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
+ *r_changed = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
return is_valid;
}
@@ -963,7 +963,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
int BKE_mesh_validate(Mesh *me, const int do_verbose)
{
bool is_valid = true;
- bool is_change;
+ bool changed;
if (do_verbose) {
printf("MESH: %s\n", me->id.name + 2);
@@ -973,7 +973,7 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose)
&me->vdata, &me->edata, &me->ldata, &me->pdata,
true,
do_verbose, true,
- &is_change);
+ &changed);
is_valid &= BKE_mesh_validate_arrays(
me,
@@ -984,9 +984,9 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose)
me->mpoly, me->totpoly,
me->dvert,
do_verbose, true,
- &is_change);
+ &changed);
- if (is_change) {
+ if (changed) {
DAG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 0cdcf4e7298..7ef2505f4e9 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -2288,7 +2288,7 @@ void multires_topology_changed(Mesh *me)
MDisps *mdisp = NULL, *cur = NULL;
int i, grid = 0;
- CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totface);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS);
if (!mdisp)
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 869dbe032c9..85354e4e0d7 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -122,7 +122,6 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
node->miniwidth = 42.0f;
node->height = ntype->height;
node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
-
/* initialize the node name with the node label.
* note: do this after the initfunc so nodes get their data set which may be used in naming
* (node groups for example) */
@@ -134,10 +133,13 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
nodeUniqueName(ntree, node);
node_add_sockets_from_type(ntree, node, ntype);
-
+
if (ntype->initfunc != NULL)
ntype->initfunc(ntree, node);
-
+
+ if (ntree->typeinfo->node_add_init != NULL)
+ ntree->typeinfo->node_add_init(ntree, node);
+
/* extra init callback */
if (ntype->initfunc_api) {
PointerRNA ptr;
@@ -1588,14 +1590,14 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
}
/** \note caller needs to manage node->id user */
-void nodeFreeNode(bNodeTree *ntree, bNode *node)
+static void node_free_node_ex(bNodeTree *ntree, bNode *node, bool use_api_free_cb)
{
bNodeSocket *sock, *nextsock;
char propname_esc[MAX_IDPROP_NAME * 2];
char prefix[MAX_IDPROP_NAME * 2];
/* extra free callback */
- if (node->typeinfo && node->typeinfo->freefunc_api) {
+ if (use_api_free_cb && node->typeinfo->freefunc_api) {
PointerRNA ptr;
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
@@ -1617,7 +1619,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
BKE_animdata_fix_paths_remove((ID *)ntree, prefix);
- if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
+ if (ntree->typeinfo->free_node_cache)
ntree->typeinfo->free_node_cache(ntree, node);
/* texture node has bad habit of keeping exec data around */
@@ -1626,7 +1628,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->execdata = NULL;
}
- if (node->typeinfo && node->typeinfo->freefunc)
+ if (node->typeinfo->freefunc)
node->typeinfo->freefunc(node);
}
@@ -1654,6 +1656,11 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->update |= NTREE_UPDATE_NODES;
}
+void nodeFreeNode(bNodeTree *ntree, bNode *node)
+{
+ node_free_node_ex(ntree, node, true);
+}
+
static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
{
if (sock->prop) {
@@ -1736,7 +1743,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
(void)do_id_user;
#endif
- nodeFreeNode(ntree, node);
+ node_free_node_ex(ntree, node, false);
}
/* free interface sockets */
@@ -2507,7 +2514,7 @@ void BKE_node_clipboard_clear(void)
for (node = node_clipboard.nodes.first; node; node = node_next) {
node_next = node->next;
- nodeFreeNode(NULL, node);
+ node_free_node_ex(NULL, node, false);
}
node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
@@ -2979,22 +2986,22 @@ void nodeUpdate(bNodeTree *ntree, bNode *node)
ntree->is_updating = FALSE;
}
-int nodeUpdateID(bNodeTree *ntree, ID *id)
+bool nodeUpdateID(bNodeTree *ntree, ID *id)
{
bNode *node;
- int change = FALSE;
+ bool changed = false;
if (ELEM(NULL, id, ntree))
- return change;
+ return changed;
/* avoid reentrant updates, can be caused by RNA update callbacks */
if (ntree->is_updating)
- return change;
- ntree->is_updating = TRUE;
+ return changed;
+ ntree->is_updating = true;
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id == id) {
- change = TRUE;
+ changed = true;
node->update |= NODE_UPDATE_ID;
if (node->typeinfo->updatefunc)
node->typeinfo->updatefunc(ntree, node);
@@ -3008,7 +3015,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id)
}
ntree->is_updating = FALSE;
- return change;
+ return changed;
}
void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
@@ -3435,6 +3442,7 @@ static void registerShaderNodes(void)
register_node_type_sh_output();
register_node_type_sh_material();
register_node_type_sh_camera();
+ register_node_type_sh_lamp();
register_node_type_sh_gamma();
register_node_type_sh_brightcontrast();
register_node_type_sh_value();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 45d9d144f55..0694bde7b91 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -312,6 +312,11 @@ void BKE_object_free_derived_caches(Object *ob)
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
+ BLI_freelistN(&ob->curve_cache->bev);
+ if (ob->curve_cache->path) {
+ free_path(ob->curve_cache->path);
+ ob->curve_cache->path = NULL;
+ }
}
}
@@ -942,7 +947,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->empty_drawtype = OB_PLAINAXES;
ob->empty_drawsize = 1.0;
- if (type == OB_CAMERA || type == OB_LAMP || type == OB_SPEAKER) {
+ if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@@ -2411,7 +2416,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
BoundBox bb;
float vec[3];
int a;
- bool change = false;
+ bool changed = false;
switch (ob->type) {
case OB_CURVE:
@@ -2424,7 +2429,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
mul_m4_v3(ob->obmat, bb.vec[a]);
minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
}
- change = TRUE;
+ changed = true;
break;
}
case OB_LATTICE:
@@ -2441,7 +2446,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
}
}
}
- change = TRUE;
+ changed = true;
break;
}
case OB_ARMATURE:
@@ -2459,7 +2464,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
minmax_v3v3_v3(min_r, max_r, vec);
- change = TRUE;
+ changed = true;
}
}
}
@@ -2476,7 +2481,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
mul_m4_v3(ob->obmat, bb.vec[a]);
minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
}
- change = TRUE;
+ changed = true;
}
break;
}
@@ -2484,8 +2489,8 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
{
float ob_min[3], ob_max[3];
- change = BKE_mball_minmax_ex(ob->data, ob_min, ob_max, ob->obmat, 0);
- if (change) {
+ changed = BKE_mball_minmax_ex(ob->data, ob_min, ob_max, ob->obmat, 0);
+ if (changed) {
minmax_v3v3_v3(min_r, max_r, ob_min);
minmax_v3v3_v3(min_r, max_r, ob_max);
}
@@ -2493,7 +2498,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
}
}
- if (change == FALSE) {
+ if (changed == false) {
float size[3];
copy_v3_v3(size, ob->size);
@@ -2539,7 +2544,7 @@ bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_m
minmax_v3v3_v3(r_min, r_max, vec);
}
- ok = TRUE;
+ ok = true;
}
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 24cf98d957d..b5825dab7c0 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3510,7 +3510,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
if (BLI_countlist(&ob->particlesystem) > 1)
BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
else
- strcpy(psys->name, DATA_("ParticleSystem"));
+ BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
md = modifier_new(eModifierType_ParticleSystem);
@@ -3525,7 +3525,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
BLI_addtail(&ob->modifiers, md);
psys->totpart = 0;
- psys->flag = PSYS_ENABLED | PSYS_CURRENT;
+ psys->flag = PSYS_CURRENT;
psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1);
DAG_relations_tag_update(G.main);
@@ -3652,6 +3652,7 @@ static void default_particle_settings(ParticleSettings *part)
if (!part->effector_weights)
part->effector_weights = BKE_add_effector_weights(NULL);
+ part->omat = 1;
part->use_modifier_stack = false;
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 9891a8cde28..d2ef59b238f 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1769,7 +1769,7 @@ static void ptcache_file_pointers_init(PTCacheFile *pf)
/* Check to see if point number "index" is in pm, uses binary search for index data. */
int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
{
- if (pm->data[BPHYS_DATA_INDEX]) {
+ if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
unsigned int *data = pm->data[BPHYS_DATA_INDEX];
unsigned int mid, low = 0, high = pm->totpoint - 1;
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 7c374fd5d78..b0b64cac802 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
@@ -405,8 +406,8 @@ void init_actuator(bActuator *act)
sa->sound3D.rolloff_factor = 1.0f;
sa->sound3D.reference_distance = 1.0f;
sa->sound3D.max_gain = 1.0f;
- sa->sound3D.cone_inner_angle = 360.0f;
- sa->sound3D.cone_outer_angle = 360.0f;
+ sa->sound3D.cone_inner_angle = DEG2RADF(360.0f);
+ sa->sound3D.cone_outer_angle = DEG2RADF(360.0f);
sa->sound3D.max_distance = FLT_MAX;
break;
case ACT_OBJECT:
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 985eae18570..80fcee18513 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -163,6 +163,9 @@ Scene *BKE_scene_copy(Scene *sce, int type)
scen->gm = sce->gm;
scen->audio = sce->audio;
+ if (sce->id.properties)
+ scen->id.properties = IDP_CopyProperty(sce->id.properties);
+
MEM_freeN(scen->toolsettings);
}
else {
@@ -435,7 +438,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.im_format.imtype = R_IMF_IMTYPE_PNG;
sce->r.im_format.depth = R_IMF_CHAN_DEPTH_8;
sce->r.im_format.quality = 90;
- sce->r.im_format.compress = 90;
+ sce->r.im_format.compress = 15;
sce->r.displaymode = R_OUTPUT_AREA;
sce->r.framapto = 100;
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index c41c66ef561..5b1bb7854a5 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -417,7 +417,7 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short
return big;
}
-void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene)
+void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
{
int bit;
@@ -481,6 +481,37 @@ void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene)
}
}
+void BKE_screen_view3d_twmode_remove(View3D *v3d, const int i)
+{
+ const int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
+ if (selected_index == i) {
+ v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
+ }
+ else if (selected_index > i) {
+ v3d->twmode--;
+ }
+}
+
+void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, Scene *scene, const int i)
+{
+ bScreen *sc;
+
+ for (sc = screen_lb->first; sc; sc = sc->id.next) {
+ if (sc->scene == scene) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ BKE_screen_view3d_twmode_remove(v3d, i);
+ }
+ }
+ }
+ }
+ }
+}
+
/* magic zoom calculation, no idea what
* it signifies, if you find out, tell me! -zr
*/
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 7b3f18c1bd4..1507e1742cd 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -1246,8 +1246,8 @@ typedef struct WipeZone {
static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
{
- wipezone->flip = (wipe->angle < 0);
- wipezone->angle = tanf(DEG2RADF(fabsf(wipe->angle)));
+ wipezone->flip = (wipe->angle < 0.0f);
+ wipezone->angle = tanf(fabsf(wipe->angle));
wipezone->xo = xo;
wipezone->yo = yo;
wipezone->width = (int)(wipe->edgeWidth * ((xo + yo) / 2.0f));
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 23f7dd6ccfb..b39f31bd1ec 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -536,7 +536,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->time_scale = 1.0;
smd->domain->vorticity = 2.0;
smd->domain->border_collisions = SM_BORDER_OPEN; // open domain
- smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG | MOD_SMOKE_HIGH_SMOOTH;
+ smd->domain->flags = MOD_SMOKE_DISSOLVE_LOG;
smd->domain->highres_sampling = SM_HRES_FULLSAMPLE;
smd->domain->strength = 2.0;
smd->domain->noise = MOD_SMOKE_NOISEWAVE;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 5011080234e..4e2f708eae4 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -234,7 +234,7 @@ static float _final_goal(Object *ob, BodyPoint *bp)/*jow_go_for2_5 */
if (!(ob->softflag & OB_SB_GOAL)) return (0.0f);
if (sb&&bp) {
if (bp->goal < 0.0f) return (0.0f);
- f = sb->mingoal + bp->goal*ABS(sb->maxgoal - sb->mingoal);
+ f = sb->mingoal + bp->goal * fabsf(sb->maxgoal - sb->mingoal);
f = pow(f, 4.0f);
return (f);
}
@@ -316,7 +316,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
/* blow it up with forcefield ranges */
- hull = MAX2(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
+ hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
/* alloc and copy verts*/
pccd_M->mvert = MEM_dupallocN(cmd->xnew);
@@ -325,13 +325,13 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
for (i=0; i < pccd_M->totvert; i++) {
/* evaluate limits */
copy_v3_v3(v, pccd_M->mvert[i].co);
- pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0], v[0]-hull);
- pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1], v[1]-hull);
- pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2], v[2]-hull);
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
- pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0], v[0]+hull);
- pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1], v[1]+hull);
- pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2], v[2]+hull);
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
}
/* alloc and copy faces*/
@@ -349,44 +349,43 @@ static ccd_Mesh *ccd_mesh_make(Object *ob)
mima->maxx=mima->maxy=mima->maxz=-1e30f;
copy_v3_v3(v, pccd_M->mvert[mface->v1].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mvert[mface->v2].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mvert[mface->v3].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
if (mface->v4) {
copy_v3_v3(v, pccd_M->mvert[mface->v4].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
}
-
- mima++;
- mface++;
-
+ mima++;
+ mface++;
}
+
return pccd_M;
}
static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
@@ -414,7 +413,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
/* blow it up with forcefield ranges */
- hull = MAX2(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
+ hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
/* rotate current to previous */
if (pccd_M->mprevvert) MEM_freeN(pccd_M->mprevvert);
@@ -426,23 +425,23 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
for (i=0; i < pccd_M->totvert; i++) {
/* evaluate limits */
copy_v3_v3(v, pccd_M->mvert[i].co);
- pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0], v[0]-hull);
- pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1], v[1]-hull);
- pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2], v[2]-hull);
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
- pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0], v[0]+hull);
- pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1], v[1]+hull);
- pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2], v[2]+hull);
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
/* evaluate limits */
copy_v3_v3(v, pccd_M->mprevvert[i].co);
- pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0], v[0]-hull);
- pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1], v[1]-hull);
- pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2], v[2]-hull);
+ pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
+ pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
+ pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
- pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0], v[0]+hull);
- pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1], v[1]+hull);
- pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2], v[2]+hull);
+ pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
+ pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
+ pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
}
@@ -456,72 +455,72 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
mima->maxx=mima->maxy=mima->maxz=-1e30f;
copy_v3_v3(v, pccd_M->mvert[mface->v1].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mvert[mface->v2].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mvert[mface->v3].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
if (mface->v4) {
copy_v3_v3(v, pccd_M->mvert[mface->v4].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
}
copy_v3_v3(v, pccd_M->mprevvert[mface->v1].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mprevvert[mface->v2].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
copy_v3_v3(v, pccd_M->mprevvert[mface->v3].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
if (mface->v4) {
copy_v3_v3(v, pccd_M->mprevvert[mface->v4].co);
- mima->minx = MIN2(mima->minx, v[0]-hull);
- mima->miny = MIN2(mima->miny, v[1]-hull);
- mima->minz = MIN2(mima->minz, v[2]-hull);
- mima->maxx = MAX2(mima->maxx, v[0]+hull);
- mima->maxy = MAX2(mima->maxy, v[1]+hull);
- mima->maxz = MAX2(mima->maxz, v[2]+hull);
+ mima->minx = min_ff(mima->minx, v[0] - hull);
+ mima->miny = min_ff(mima->miny, v[1] - hull);
+ mima->minz = min_ff(mima->minz, v[2] - hull);
+ mima->maxx = max_ff(mima->maxx, v[0] + hull);
+ mima->maxy = max_ff(mima->maxy, v[1] + hull);
+ mima->maxz = max_ff(mima->maxz, v[2] + hull);
}
@@ -818,10 +817,10 @@ static void calculate_collision_balls(Object *ob)
for (b=bp->nofsprings;b>0;b--) {
bs = sb->bspring + bp->springs[b-1];
if (bs->springtype == SB_EDGE) {
- akku += bs->len;
- akku_count++,
- min = MIN2(bs->len, min);
- max = MAX2(bs->len, max);
+ akku += bs->len;
+ akku_count++;
+ min = min_ff(bs->len, min);
+ max = max_ff(bs->len, max);
}
}
@@ -1345,24 +1344,26 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
bf->flag &= ~BFF_INTERSECT;
feedback[0]=feedback[1]=feedback[2]=0.0f;
if (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
- &damp, feedback, ob->lay, ob, timenow)) {
+ &damp, feedback, ob->lay, ob, timenow))
+ {
Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
Vec3PlusStVec(sb->bpoint[bf->v2].force, tune, feedback);
Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
// Vec3PlusStVec(bf->ext_force, tune, feedback);
bf->flag |= BFF_INTERSECT;
- choke = MIN2(MAX2(damp, choke), 1.0f);
+ choke = min_ff(max_ff(damp, choke), 1.0f);
}
feedback[0]=feedback[1]=feedback[2]=0.0f;
if ((bf->v4) && (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos, sb->bpoint[bf->v3].pos, sb->bpoint[bf->v4].pos,
- &damp, feedback, ob->lay, ob, timenow))) {
+ &damp, feedback, ob->lay, ob, timenow)))
+ {
Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
Vec3PlusStVec(sb->bpoint[bf->v4].force, tune, feedback);
// Vec3PlusStVec(bf->ext_force, tune, feedback);
bf->flag |= BFF_INTERSECT;
- choke = MIN2(MAX2(damp, choke), 1.0f);
+ choke = min_ff(max_ff(damp, choke), 1.0f);
}
/*---edges intruding*/
@@ -1372,24 +1373,26 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
tune = -1.0f;
feedback[0]=feedback[1]=feedback[2]=0.0f;
if (sb_detect_face_pointCached(sb->bpoint[bf->v1].pos, sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
- &damp, feedback, ob->lay, ob, timenow)) {
- Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
- Vec3PlusStVec(sb->bpoint[bf->v2].force, tune, feedback);
- Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
-// Vec3PlusStVec(bf->ext_force, tune, feedback);
- bf->flag |= BFF_CLOSEVERT;
- choke = MIN2(MAX2(damp, choke), 1.0f);
+ &damp, feedback, ob->lay, ob, timenow))
+ {
+ Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
+ Vec3PlusStVec(sb->bpoint[bf->v2].force, tune, feedback);
+ Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
+// Vec3PlusStVec(bf->ext_force, tune, feedback);
+ bf->flag |= BFF_CLOSEVERT;
+ choke = min_ff(max_ff(damp, choke), 1.0f);
}
feedback[0]=feedback[1]=feedback[2]=0.0f;
if ((bf->v4) && (sb_detect_face_pointCached(sb->bpoint[bf->v1].pos, sb->bpoint[bf->v3].pos, sb->bpoint[bf->v4].pos,
- &damp, feedback, ob->lay, ob, timenow))) {
- Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
- Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
- Vec3PlusStVec(sb->bpoint[bf->v4].force, tune, feedback);
-// Vec3PlusStVec(bf->ext_force, tune, feedback);
- bf->flag |= BFF_CLOSEVERT;
- choke = MIN2(MAX2(damp, choke), 1.0f);
+ &damp, feedback, ob->lay, ob, timenow)))
+ {
+ Vec3PlusStVec(sb->bpoint[bf->v1].force, tune, feedback);
+ Vec3PlusStVec(sb->bpoint[bf->v3].force, tune, feedback);
+ Vec3PlusStVec(sb->bpoint[bf->v4].force, tune, feedback);
+// Vec3PlusStVec(bf->ext_force, tune, feedback);
+ bf->flag |= BFF_CLOSEVERT;
+ choke = min_ff(max_ff(damp, choke), 1.0f);
}
}
/*--- close vertices*/
@@ -1397,11 +1400,11 @@ static void scan_for_ext_face_forces(Object *ob, float timenow)
bf = sb->scratch->bodyface;
for (a=0; a<sb->scratch->totface; a++, bf++) {
if (( bf->flag & BFF_INTERSECT) || ( bf->flag & BFF_CLOSEVERT)) {
- sb->bpoint[bf->v1].choke2=MAX2(sb->bpoint[bf->v1].choke2, choke);
- sb->bpoint[bf->v2].choke2=MAX2(sb->bpoint[bf->v2].choke2, choke);
- sb->bpoint[bf->v3].choke2=MAX2(sb->bpoint[bf->v3].choke2, choke);
+ sb->bpoint[bf->v1].choke2 = max_ff(sb->bpoint[bf->v1].choke2, choke);
+ sb->bpoint[bf->v2].choke2 = max_ff(sb->bpoint[bf->v2].choke2, choke);
+ sb->bpoint[bf->v3].choke2 = max_ff(sb->bpoint[bf->v3].choke2, choke);
if (bf->v4) {
- sb->bpoint[bf->v2].choke2=MAX2(sb->bpoint[bf->v2].choke2, choke);
+ sb->bpoint[bf->v2].choke2 = max_ff(sb->bpoint[bf->v2].choke2, choke);
}
}
}
@@ -1423,12 +1426,8 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
float t, el;
int a, deflected=0;
- aabbmin[0] = MIN2(edge_v1[0], edge_v2[0]);
- aabbmin[1] = MIN2(edge_v1[1], edge_v2[1]);
- aabbmin[2] = MIN2(edge_v1[2], edge_v2[2]);
- aabbmax[0] = MAX2(edge_v1[0], edge_v2[0]);
- aabbmax[1] = MAX2(edge_v1[1], edge_v2[1]);
- aabbmax[2] = MAX2(edge_v1[2], edge_v2[2]);
+ minmax_v3v3_v3(aabbmin, aabbmax, edge_v1);
+ minmax_v3v3_v3(aabbmin, aabbmax, edge_v2);
el = len_v3v3(edge_v1, edge_v2);
@@ -1481,7 +1480,8 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
(aabbmin[1] > mima->maxy) ||
(aabbmax[2] < mima->minz) ||
(aabbmin[2] > mima->maxz)
- ) {
+ )
+ {
mface++;
mima++;
continue;
@@ -1526,7 +1526,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
sub_v3_v3v3(v2, edge_v2, nv2);
i1 = dot_v3v3(v1, d_nvect);
i2 = dot_v3v3(v2, d_nvect);
- intrusiondepth = -MIN2(i1, i2)/el;
+ intrusiondepth = -min_ff(i1, i2) / el;
Vec3PlusStVec(force, intrusiondepth, d_nvect);
*damp=ob->pd->pdef_sbdamp;
deflected = 2;
@@ -1543,9 +1543,9 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
float intrusiondepth, i1, i2;
sub_v3_v3v3(v1, edge_v1, nv4);
sub_v3_v3v3(v2, edge_v2, nv4);
- i1 = dot_v3v3(v1, d_nvect);
- i2 = dot_v3v3(v2, d_nvect);
- intrusiondepth = -MIN2(i1, i2)/el;
+ i1 = dot_v3v3(v1, d_nvect);
+ i2 = dot_v3v3(v2, d_nvect);
+ intrusiondepth = -min_ff(i1, i2) / el;
Vec3PlusStVec(force, intrusiondepth, d_nvect);
@@ -1624,7 +1624,7 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
normalize_v3(vel);
if (ob->softflag & OB_SB_AERO_ANGLE) {
normalize_v3(sp);
- Vec3PlusStVec(bs->ext_force, f*(1.0f-ABS(dot_v3v3(vel, sp))), vel);
+ Vec3PlusStVec(bs->ext_force, f * (1.0f - fabsf(dot_v3v3(vel, sp))), vel);
}
else {
Vec3PlusStVec(bs->ext_force, f, vel); // to keep compatible with 2.45 release files
@@ -2947,9 +2947,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
/* compare euler to heun to estimate error for step sizing */
- maxerrvel = MAX2(maxerrvel, ABS(dv[0] - bp->prevdv[0]));
- maxerrvel = MAX2(maxerrvel, ABS(dv[1] - bp->prevdv[1]));
- maxerrvel = MAX2(maxerrvel, ABS(dv[2] - bp->prevdv[2]));
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[0] - bp->prevdv[0]));
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[1] - bp->prevdv[1]));
+ maxerrvel = max_ff(maxerrvel, fabsf(dv[2] - bp->prevdv[2]));
}
else { add_v3_v3(bp->vec, bp->force); }
@@ -2962,15 +2962,15 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
mul_v3_fl(dx, forcetime);
/* the freezer coming sooner or later */
- /*
+#if 0
if ((dot_v3v3(dx, dx)<freezeloc )&&(dot_v3v3(bp->force, bp->force)<freezeforce )) {
bp->frozen /=2;
}
else {
- bp->frozen = MIN2(bp->frozen*1.05f, 1.0f);
+ bp->frozen = min_ff(bp->frozen*1.05f, 1.0f);
}
mul_v3_fl(dx, bp->frozen);
- */
+#endif
/* again some nasty if's to have heun in here too */
if (mode ==1) {
copy_v3_v3(bp->prevpos, bp->pos);
@@ -2981,9 +2981,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
bp->pos[2] = bp->prevpos[2] + 0.5f * ( dx[2] + bp->prevdx[2]);
- maxerrpos = MAX2(maxerrpos, ABS(dx[0] - bp->prevdx[0]));
- maxerrpos = MAX2(maxerrpos, ABS(dx[1] - bp->prevdx[1]));
- maxerrpos = MAX2(maxerrpos, ABS(dx[2] - bp->prevdx[2]));
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[0] - bp->prevdx[0]));
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[1] - bp->prevdx[1]));
+ maxerrpos = max_ff(maxerrpos, fabsf(dx[2] - bp->prevdx[2]));
/* bp->choke is set when we need to pull a vertex or edge out of the collider.
* the collider object signals to get out by pushing hard. on the other hand
@@ -3000,12 +3000,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
else { add_v3_v3(bp->pos, dx);}
}/*snap*/
/* so while we are looping BPs anyway do statistics on the fly */
- aabbmin[0] = MIN2(aabbmin[0], bp->pos[0]);
- aabbmin[1] = MIN2(aabbmin[1], bp->pos[1]);
- aabbmin[2] = MIN2(aabbmin[2], bp->pos[2]);
- aabbmax[0] = MAX2(aabbmax[0], bp->pos[0]);
- aabbmax[1] = MAX2(aabbmax[1], bp->pos[1]);
- aabbmax[2] = MAX2(aabbmax[2], bp->pos[2]);
+ minmax_v3v3_v3(aabbmin, aabbmax, bp->pos);
if (bp->loc_flag & SBF_DOFUZZY) fuzzy =1;
} /*for*/
@@ -3017,9 +3012,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
if (err) { /* so step size will be controlled by biggest difference in slope */
if (sb->solverflags & SBSO_OLDERR)
- *err = MAX2(maxerrpos, maxerrvel);
+ *err = max_ff(maxerrpos, maxerrvel);
else
- *err = maxerrpos;
+ *err = maxerrpos;
//printf("EP %f EV %f\n", maxerrpos, maxerrvel);
if (fuzzy) {
*err /= sb->fuzzyness;
@@ -3972,7 +3967,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
if (forcetime > forcetimemin) {
- forcetime = MAX2(forcetime / 2.0f, forcetimemin);
+ forcetime = max_ff(forcetime / 2.0f, forcetimemin);
softbody_restore_prev_step(ob);
//printf("down, ");
}
@@ -3994,12 +3989,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
}
}
timedone += forcetime;
- newtime=MIN2(forcetimemax, MAX2(newtime, forcetimemin));
+ newtime = min_ff(forcetimemax, max_ff(newtime, forcetimemin));
//if (newtime > forcetime) printf("up, ");
if (forcetime > 0.0f)
- forcetime = MIN2(dtime - timedone, newtime);
+ forcetime = min_ff(dtime - timedone, newtime);
else
- forcetime = MAX2(dtime - timedone, newtime);
+ forcetime = max_ff(dtime - timedone, newtime);
}
loops++;
if (sb->solverflags & SBSO_MONITOR ) {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index be43aae1ed3..96601985f67 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -2650,22 +2650,26 @@ void txt_indent(Text *text)
num = 0;
while (TRUE) {
- tmp = MEM_mallocN(text->curl->len + indentlen + 1, "textline_string");
-
- text->curc = 0;
- if (text->curc) memcpy(tmp, text->curl->line, text->curc); /* XXX never true, check prev line */
- memcpy(tmp + text->curc, add, indentlen);
-
- len = text->curl->len - text->curc;
- if (len > 0) memcpy(tmp + text->curc + indentlen, text->curl->line + text->curc, len);
- tmp[text->curl->len + indentlen] = 0;
- make_new_line(text->curl, tmp);
-
- text->curc += indentlen;
-
- txt_make_dirty(text);
- txt_clean_text(text);
+ /* don't indent blank lines */
+ if (text->curl->len != 0) {
+ tmp = MEM_mallocN(text->curl->len + indentlen + 1, "textline_string");
+
+ text->curc = 0;
+ if (text->curc) memcpy(tmp, text->curl->line, text->curc); /* XXX never true, check prev line */
+ memcpy(tmp + text->curc, add, indentlen);
+
+ len = text->curl->len - text->curc;
+ if (len > 0) memcpy(tmp + text->curc + indentlen, text->curl->line + text->curc, len);
+ tmp[text->curl->len + indentlen] = 0;
+
+ make_new_line(text->curl, tmp);
+
+ text->curc += indentlen;
+
+ txt_make_dirty(text);
+ txt_clean_text(text);
+ }
if (text->curl == text->sell) {
text->selc += indentlen;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index d519b93f963..355922d157a 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1344,6 +1344,8 @@ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, L
/* Use some default name. */
strcpy(plane_track->name, "Plane Track");
+ plane_track->image_opacity = 1.0f;
+
/* Use selected tracks from given list as a plane. */
plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array");
for (track = tracks->first, track_index = 0; track; track = track->next) {
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 64470542844..17aad7a5a2c 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -392,7 +392,7 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC
while (unit->name_short[j] && (i < len_max)) {
str[i++] = unit->name_short[j++];
}
-
+#if 0
if (pad) {
/* this loop only runs if so many zeros were removed that
* the unit name only used padded chars,
@@ -402,6 +402,7 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC
str[i++] = pad;
}
}
+#endif
}
/* terminate no matter whats done with padding above */
@@ -599,7 +600,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
bUnitDef *unit;
char str_tmp[TEMP_STR_SIZE];
- int change = 0;
+ int changed = 0;
if (usys == NULL || usys->units[0].name == NULL) {
return 0;
@@ -618,7 +619,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
for (unit = usys->units; unit->name; unit++) {
/* in case there are multiple instances */
while (unit_replace(str, len_max, str_tmp, scale_pref, unit))
- change = 1;
+ changed = true;
}
unit = NULL;
@@ -635,7 +636,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
int ofs = 0;
/* in case there are multiple instances */
while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit)))
- change = 1;
+ changed = true;
}
}
}
@@ -643,7 +644,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
}
unit = NULL;
- if (change == 0) {
+ if (changed == 0) {
/* no units given so infer a unit from the previous string or default */
if (str_prev) {
/* see which units the original value had */
@@ -701,7 +702,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca
}
}
- return change;
+ return changed;
}
/* 45µm --> 45um */
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index ff6212f6b09..1d29ef70d8b 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -132,9 +132,16 @@ static void filepath_avi(char *string, RenderData *rd)
BLI_make_existing_file(string);
- if (!BLI_testextensie(string, ".avi")) {
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
- strcat(string, ".avi");
+ if (rd->scemode & R_EXTENSION) {
+ if (!BLI_testextensie(string, ".avi")) {
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ strcat(string, ".avi");
+ }
+ }
+ else {
+ if (BLI_path_frame_check_chars(string)) {
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ }
}
}
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index bcf5e712eff..ff4300c34e9 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -1023,23 +1023,32 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
sprintf(autosplit, "_%03d", ffmpeg_autosplit_count);
}
- while (*fe) {
- if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) {
- break;
+ if (rd->scemode & R_EXTENSION) {
+ while (*fe) {
+ if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) {
+ break;
+ }
+ fe++;
}
- fe++;
- }
- if (*fe == NULL) {
- strcat(string, autosplit);
+ if (*fe == NULL) {
+ strcat(string, autosplit);
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
- strcat(string, *exts);
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ strcat(string, *exts);
+ }
+ else {
+ *(string + strlen(string) - strlen(*fe)) = 0;
+ strcat(string, autosplit);
+ strcat(string, *fe);
+ }
}
else {
- *(string + strlen(string) - strlen(*fe)) = 0;
+ if (BLI_path_frame_check_chars(string)) {
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ }
+
strcat(string, autosplit);
- strcat(string, *fe);
}
}
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index c9fb00ecdf5..ef78fb9a305 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -147,6 +147,17 @@
(_BLI_SMALLSTACK_CAST(var) ((_##var##_stack) ? \
(_BLI_SMALLSTACK_DEL(var), (_##var##_free->link)) : NULL))
+/* loop over stack members last-added-first */
+#define BLI_SMALLSTACK_ITER_BEGIN(var, item) \
+ { \
+ LinkNode *_##var##_iter; \
+ for (_##var##_iter = _##var##_stack; _##var##_iter; _##var##_iter = _##var##_iter->next) { \
+ item = _BLI_SMALLSTACK_CAST(var) (_##var##_iter->link); \
+
+#define BLI_SMALLSTACK_ITER_END \
+ } \
+ } (void)0
+
#define BLI_SMALLSTACK_FREE(var) { \
(void)&(_##var##_type); \
} (void)0
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 1cb28d25b6c..99d9397f218 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -139,14 +139,21 @@ static const int NAN_INT = 0x7FC00000;
#ifndef hypotf
#define hypotf(a, b) ((float)hypot(a, b))
#endif
+#ifndef copysignf
+#define copysignf(a, b) ((float)copysign(a, b))
+#endif
#endif /* C99 or POSIX.1-2001 */
#ifdef WIN32
# ifndef FREE_WINDOWS
-# define isnan(n) _isnan(n)
+# ifndef isnan
+# define isnan(n) _isnan(n)
+# endif
# define finite _finite
-# define hypot _hypot
+# ifndef hypot
+# define hypot(a, b) _hypot(a, b)
+# endif
# endif
#endif
@@ -176,13 +183,6 @@ static const int NAN_INT = 0x7FC00000;
} (void)0
#endif
-#ifndef CLAMP
-# define CLAMP(a, b, c) { \
- if ((a) < (b)) (a) = (b); \
- else if ((a) > (c)) (a) = (c); \
-} (void)0
-#endif
-
#if BLI_MATH_DO_INLINE
#include "intern/math_base_inline.c"
#endif
@@ -197,6 +197,8 @@ static const int NAN_INT = 0x7FC00000;
MINLINE float sqrt3f(float f);
MINLINE double sqrt3d(double d);
+MINLINE float sqrtf_signed(float f);
+
MINLINE float saacosf(float f);
MINLINE float saasinf(float f);
MINLINE float sasqrtf(float f);
@@ -208,9 +210,17 @@ MINLINE float interpf(float a, float b, float t);
MINLINE float min_ff(float a, float b);
MINLINE float max_ff(float a, float b);
+MINLINE float min_fff(float a, float b, float c);
+MINLINE float max_fff(float a, float b, float c);
+MINLINE float min_ffff(float a, float b, float c, float d);
+MINLINE float max_ffff(float a, float b, float c, float d);
MINLINE int min_ii(int a, int b);
MINLINE int max_ii(int a, int b);
+MINLINE int min_iii(int a, int b, int c);
+MINLINE int max_iii(int a, int b, int c);
+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);
@@ -224,6 +234,9 @@ MINLINE int power_of_2_min_i(int n);
MINLINE int divide_round_i(int a, int b);
MINLINE int mod_i(int i, int n);
+MINLINE unsigned int highest_order_bit_i(unsigned int n);
+MINLINE unsigned short highest_order_bit_s(unsigned short n);
+
MINLINE float shell_angle_to_dist(const float angle);
#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 6f432761a55..7167aad9551 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -76,7 +76,12 @@ void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z);
unsigned int rgb_to_cpack(float r, float g, float b);
unsigned int hsv_to_cpack(float h, float s, float v);
-/* rgb_to_grayscale & rgb_to_luma functions moved to math_color_inline.c */
+MINLINE float rgb_to_bw(const float rgb[3]);
+MINLINE float rgb_to_grayscale(const float rgb[3]);
+MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]);
+MINLINE float rgb_to_luma(const float rgb[3]);
+MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3]);
+MINLINE float rgb_to_luma_y(const float rgb[3]);
/**************** Profile Transformations *****************/
@@ -95,6 +100,11 @@ MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]);
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]);
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]);
+MINLINE unsigned short to_srgb_table_lookup(const float f);
+MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4]);
+MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4]);
+MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4]);
+
MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3]);
MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4]);
@@ -126,6 +136,13 @@ void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b);
MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], const int limit);
+#define rgba_char_args_set_fl(col, r, g, b, a) \
+ rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
+
+MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a);
+MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a);
+MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack);
+
/********* lift/gamma/gain / ASC-CDL conversion ***********/
void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index f815716148b..4f41ac86a0e 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -54,14 +54,17 @@ void cent_quad_v3(float r[3], const float a[3], const float b[3], const float c[
float normal_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]);
float normal_quad_v3(float r[3], const float a[3], const float b[3], const float c[3], const float d[3]);
-float area_tri_v2(const float a[2], const float b[2], const float c[2]);
-float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]);
+MINLINE float area_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_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_poly_v3(int nr, float verts[][3], const float normal[3]);
float area_poly_v2(int nr, float verts[][2]);
+MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]);
+float cross_poly_v2(int nr, float verts[][2]);
+
/********************************* Planes **********************************/
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]);
@@ -219,6 +222,8 @@ int barycentric_inside_triangle_v2(const float w[3]);
void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]);
void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]);
+void resolve_quad_uv_deriv(float r_uv[2], float r_deriv[2][2],
+ const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]);
/* use to find the point of a UV on a face */
void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]);
@@ -279,6 +284,7 @@ MINLINE void zero_sh(float r[9]);
MINLINE void copy_sh_sh(float r[9], const float a[9]);
MINLINE void mul_sh_fl(float r[9], const float f);
MINLINE void add_sh_shsh(float r[9], const float a[9], const float b[9]);
+MINLINE float dot_shsh(const float a[9], const float b[9]);
MINLINE float eval_shv3(float r[9], const float v[3]);
MINLINE float diffuse_shv3(float r[9], const float v[3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 3ff81e478c9..3c0f215b165 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -83,6 +83,7 @@ MINLINE void copy_v2db_v2fl(double r[2], const float a[2]);
MINLINE void copy_v3db_v3fl(double r[3], const float a[3]);
MINLINE void copy_v4db_v4fl(double r[4], const float a[4]);
/* float args -> vec */
+MINLINE void copy_v2_fl2(float v[2], float x, float y);
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z);
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w);
@@ -124,6 +125,7 @@ MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_
MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f);
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f);
MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f);
@@ -143,6 +145,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_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;
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]);
@@ -172,6 +175,7 @@ MINLINE float normalize_v2(float r[2]);
MINLINE float normalize_v2_v2(float r[2], const float a[2]);
MINLINE float normalize_v3(float r[3]);
MINLINE float normalize_v3_v3(float r[3], const float a[3]);
+MINLINE double normalize_v3_d(double n[3]);
/******************************* Interpolation *******************************/
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index 737324ebc16..8d5a7654425 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -52,12 +52,13 @@ extern "C" {
struct MemArena;
typedef struct MemArena MemArena;
-struct MemArena *BLI_memarena_new(const int bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC;
+struct MemArena *BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC;
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1);
void BLI_memarena_use_malloc(struct MemArena *ma) ATTR_NONNULL(1);
void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1);
-void BLI_memarena_use_align(struct MemArena *ma, const int align) ATTR_NONNULL(1);
-void *BLI_memarena_alloc(struct MemArena *ma, int size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
+void BLI_memarena_use_align(struct MemArena *ma, const size_t align) ATTR_NONNULL(1);
+void *BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
+void *BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index d4c5d5fed9f..0cffa286014 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -117,9 +117,9 @@ bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch);
bool BLI_replace_extension(char *path, size_t maxlen, const char *ext);
bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext);
bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename);
-void BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, short name_offs, short len);
+void BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int len);
bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
- void *arg, const char * defname, char delim, char *name, short name_len);
+ void *arg, const char *defname, char delim, char *name, int name_len);
void BLI_newname(char *name, int add);
int BLI_stringdec(const char *string, char *head, char *start, unsigned short *numlen);
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic);
@@ -158,6 +158,7 @@ bool BLI_has_parent(char *path);
bool BLI_path_abs(char *path, const char *basepath);
bool BLI_path_frame(char *path, int frame, int digits);
bool BLI_path_frame_range(char *path, int sta, int end, int digits);
+bool BLI_path_frame_check_chars(const char *path);
bool BLI_path_cwd(char *path);
void BLI_path_rel(char *file, const char *relfile);
diff --git a/source/blender/blenlib/BLI_polyfill2d.h b/source/blender/blenlib/BLI_polyfill2d.h
new file mode 100644
index 00000000000..40ac4cc0ad0
--- /dev/null
+++ b/source/blender/blenlib/BLI_polyfill2d.h
@@ -0,0 +1,44 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_POLYFILL2D_H__
+#define __BLI_POLYFILL2D_H__
+
+void BLI_polyfill_calc_ex(
+ const float (*coords)[2],
+ const unsigned int count,
+ unsigned int (*r_tris)[3],
+
+ /* avoid allocating each time */
+ unsigned int *r_indices, signed char *r_coords_sign);
+
+void BLI_polyfill_calc_arena(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*r_tris)[3],
+
+ struct MemArena *arena);
+
+void BLI_polyfill_calc(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*r_tris)[3]);
+
+#endif /* __BLI_POLYFILL2D_H__ */
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index 0fee9264191..dddfb8c6ea9 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -68,8 +68,12 @@ bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, cons
bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest);
+bool BLI_rcti_isect_x(const rcti *rect, const int x);
+bool BLI_rcti_isect_y(const rcti *rect, const int y);
bool BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y);
bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]);
+bool BLI_rctf_isect_x(const rctf *rect, const float x);
+bool BLI_rctf_isect_y(const rctf *rect, const float y);
bool BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y);
bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]);
bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 9bf720c03ea..ef2c61cc45a 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -48,14 +48,38 @@
#endif
/* min/max */
+#if defined(__GNUC__) || defined(__clang__)
+
+#define MIN2(x, y) ({ \
+ typeof(x) x_ = (x); \
+ typeof(y) y_ = (y); \
+ ((x_) < (y_) ? (x_) : (y_)); })
+
+#define MAX2(x, y) ({ \
+ typeof(x) x_ = (x); \
+ typeof(y) y_ = (y); \
+ ((x_) > (y_) ? (x_) : (y_)); })
+
+#else
#define MIN2(x, y) ((x) < (y) ? (x) : (y))
+#define MAX2(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
#define MIN3(x, y, z) (MIN2(MIN2((x), (y)), (z)))
#define MIN4(x, y, z, a) (MIN2(MIN2((x), (y)), MIN2((z), (a))))
-#define MAX2(x, y) ((x) > (y) ? (x) : (y))
#define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z)))
#define MAX4(x, y, z, a) (MAX2(MAX2((x), (y)), MAX2((z), (a))))
+/* min/max that return a value of our choice */
+#define MAX3_PAIR(cmp_a, cmp_b, cmp_c, ret_a, ret_b, ret_c) \
+ ((cmp_a > cmp_b) ? ((cmp_a > cmp_c) ? ret_a : ret_c) : \
+ ((cmp_b > cmp_c) ? ret_b : ret_c))
+
+#define MIN3_PAIR(cmp_a, cmp_b, cmp_c, ret_a, ret_b, ret_c) \
+ ((cmp_a < cmp_b) ? ((cmp_a < cmp_c) ? ret_a : ret_c) : \
+ ((cmp_b < cmp_c) ? ret_b : ret_c))
+
#define INIT_MINMAX(min, max) { \
(min)[0] = (min)[1] = (min)[2] = 1.0e30f; \
(max)[0] = (max)[1] = (max)[2] = -1.0e30f; \
@@ -171,9 +195,7 @@
} (void)0
-#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )
-
-#define FTOCHAR(val) ((val) <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : (char)((255.0f * (val)) + 0.5f))
+#define FTOCHAR(val) (char)(((val) <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * (val)) + 0.5f)))
#define FTOUSHORT(val) ((val >= 1.0f - 0.5f / 65535) ? 65535 : (val <= 0.0f) ? 0 : (unsigned short)(val * 65535.0f + 0.5f))
#define USHORTTOUCHAR(val) ((unsigned char)(((val) >= 65535 - 128) ? 255 : ((val) + 128) >> 8))
#define F3TOCHAR3(v2, v1) { \
@@ -233,12 +255,37 @@
} (void)0
/* some misc stuff.... */
+
+/* avoid multiple access & type conversions for supported compilers */
+#if defined(__GNUC__) || defined(__clang__)
+
+#define ABS(a) ({ \
+ typeof(a) a_ = (a); \
+ ((a_) < 0 ? (-(a_)) : (a_)); })
+
+#define CLAMPIS(a, b, c) ({ \
+ typeof(a) a_ = (a), b_ = (b), c_ = (c); \
+ ((a_) < (b_) ? (b_) : (a_) > (c_) ? (c_) : (a_)); })
+
+#define CLAMP(a, b, c) { \
+ typeof(a) b_ = (b), c_ = (c); \
+ if ((a) < (b_)) (a) = (b_); \
+ else if ((a) > (c_)) (a) = (c_); \
+} (void)0
+
+#else
+
+#define ABS(a) ((a) < 0 ? (-(a)) : (a))
+
+#define CLAMPIS(a, b, c) ((a) < (b) ? (b) : (a) > (c) ? (c) : (a))
+
#define CLAMP(a, b, c) { \
- if ((a) < (b)) (a) = (b); \
+ if ((a) < (b)) (a) = (b); \
else if ((a) > (c)) (a) = (c); \
} (void)0
-#define CLAMPIS(a, b, c) ((a) < (b) ? (b) : (a) > (c) ? (c) : (a))
+#endif
+
#define IS_EQ(a, b) ( \
CHECK_TYPE_INLINE(a, double), CHECK_TYPE_INLINE(b, double), \
@@ -291,6 +338,12 @@
#define ARRAY_HAS_ITEM(arr_item, arr_start, tot) \
((unsigned int)((arr_item) - (arr_start)) < (unsigned int)(tot))
+#define ARRAY_DELETE(arr, index, tot_delete, tot) { \
+ BLI_assert(index + tot_delete <= tot); \
+ memmove(&(arr)[(index)], \
+ &(arr)[(index) + (tot_delete)], \
+ (((tot) - (index)) - (tot_delete)) * sizeof(*(arr))); \
+ } (void)0
/* Warning-free macros for storing ints in pointers. Use these _only_
* for storing an int in a pointer, not a pointer in an int (64bit)! */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index d855d45760a..00adb375c41 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SRC
intern/md5.c
intern/noise.c
intern/path_util.c
+ intern/polyfill2d.c
intern/quadric.c
intern/rand.c
intern/rct.c
@@ -148,6 +149,7 @@ set(SRC
BLI_mempool.h
BLI_noise.h
BLI_path_util.h
+ BLI_polyfill2d.h
BLI_quadric.h
BLI_rand.h
BLI_rect.h
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 206a8041c4a..55dee4e8677 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -125,7 +125,7 @@ Heap *BLI_heap_new_ex(unsigned int tot_reserve)
{
Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__);
/* ensure we have at least one so we can keep doubling it */
- heap->bufsize = MAX2(1, tot_reserve);
+ heap->bufsize = MAX2(1u, tot_reserve);
heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena");
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index 4a6712201a9..dd0997c8e1c 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -30,10 +30,12 @@
* \ingroup bli
*/
+#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_memarena.h"
#include "BLI_linklist.h"
#include "BLI_strict_flags.h"
@@ -44,16 +46,16 @@
struct MemArena {
unsigned char *curbuf;
- int bufsize, cursize;
const char *name;
+ LinkNode *bufs;
- int use_calloc;
- int align;
+ size_t bufsize, cursize;
+ size_t align;
- LinkNode *bufs;
+ bool use_calloc;
};
-MemArena *BLI_memarena_new(const int bufsize, const char *name)
+MemArena *BLI_memarena_new(const size_t bufsize, const char *name)
{
MemArena *ma = MEM_callocN(sizeof(*ma), "memarena");
ma->bufsize = bufsize;
@@ -77,7 +79,7 @@ void BLI_memarena_use_malloc(MemArena *ma)
ma->use_calloc = 0;
}
-void BLI_memarena_use_align(struct MemArena *ma, const int align)
+void BLI_memarena_use_align(struct MemArena *ma, const size_t align)
{
/* align should be a power of two */
ma->align = align;
@@ -102,12 +104,12 @@ static void memarena_curbuf_align(MemArena *ma)
{
unsigned char *tmp;
- tmp = (unsigned char *)PADUP( (intptr_t) ma->curbuf, ma->align);
- ma->cursize -= (int)(tmp - ma->curbuf);
+ tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align);
+ ma->cursize -= (size_t)(tmp - ma->curbuf);
ma->curbuf = tmp;
}
-void *BLI_memarena_alloc(MemArena *ma, int size)
+void *BLI_memarena_alloc(MemArena *ma, size_t size)
{
void *ptr;
@@ -115,18 +117,15 @@ void *BLI_memarena_alloc(MemArena *ma, int size)
* size up to multiple of 8 */
size = PADUP(size, ma->align);
- if (size > ma->cursize) {
+ if (UNLIKELY(size > ma->cursize)) {
if (size > ma->bufsize - (ma->align - 1)) {
ma->cursize = PADUP(size + 1, ma->align);
}
- else
+ else {
ma->cursize = ma->bufsize;
+ }
- if (ma->use_calloc)
- ma->curbuf = MEM_callocN((size_t)ma->cursize, ma->name);
- else
- ma->curbuf = MEM_mallocN((size_t)ma->cursize, ma->name);
-
+ ma->curbuf = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(ma->cursize, ma->name);
BLI_linklist_prepend(&ma->bufs, ma->curbuf);
memarena_curbuf_align(ma);
}
@@ -142,6 +141,19 @@ void *BLI_memarena_alloc(MemArena *ma, int size)
return ptr;
}
+void *BLI_memarena_calloc(MemArena *ma, size_t size)
+{
+ void *ptr;
+
+ /* no need to use this function call if we're calloc'ing by default */
+ BLI_assert(ma->use_calloc == false);
+
+ ptr = BLI_memarena_alloc(ma, size);
+ memset(ptr, 0, size);
+
+ return ptr;
+}
+
/**
* Clear for reuse, avoids re-allocation when an arena may
* otherwise be free'd and recreated.
@@ -150,7 +162,7 @@ void BLI_memarena_clear(MemArena *ma)
{
if (ma->bufs) {
unsigned char *curbuf_prev;
- int curbuf_used;
+ size_t curbuf_used;
if (ma->bufs->next) {
BLI_linklist_freeN(ma->bufs->next);
@@ -162,11 +174,11 @@ void BLI_memarena_clear(MemArena *ma)
memarena_curbuf_align(ma);
/* restore to original size */
- curbuf_used = (int)(curbuf_prev - ma->curbuf);
+ curbuf_used = (size_t)(curbuf_prev - ma->curbuf);
ma->cursize += curbuf_used;
if (ma->use_calloc) {
- memset(ma->curbuf, 0, (size_t)curbuf_used);
+ memset(ma->curbuf, 0, curbuf_used);
}
}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 28539d9ca34..1321f006e36 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -257,7 +257,7 @@ BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem,
}
if (flag & BLI_MEMPOOL_ALLOW_ITER) {
- pool->esize = MAX2(esize, (int)sizeof(BLI_freenode));
+ pool->esize = MAX2(esize, (unsigned int)sizeof(BLI_freenode));
}
else {
pool->esize = esize;
@@ -295,7 +295,7 @@ void *BLI_mempool_alloc(BLI_mempool *pool)
pool->totused++;
- if (!(pool->free)) {
+ if (UNLIKELY(pool->free == NULL)) {
/* need to allocate a new chunk */
BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
mempool_chunk_add(pool, mpchunk, NULL);
diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c
index 38d303e667a..3ff1af3513e 100644
--- a/source/blender/blenlib/intern/math_base.c
+++ b/source/blender/blenlib/intern/math_base.c
@@ -27,10 +27,10 @@
* \ingroup bli
*/
-
-
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
/* WARNING: MSVC compiling hack for double_round() */
#if (defined(WIN32) || defined(WIN64)) && !(defined(FREE_WINDOWS))
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index e6509db1c5e..a215d99e32d 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -61,6 +61,11 @@ MINLINE double sqrt3d(double d)
else return exp(log( d) / 3.0);
}
+MINLINE float sqrtf_signed(float f)
+{
+ return (f >= 0.0f) ? sqrtf(f) : -sqrtf(-f);
+}
+
MINLINE float saacos(float fac)
{
if (UNLIKELY(fac <= -1.0f)) return (float)M_PI;
@@ -177,7 +182,7 @@ MINLINE unsigned short highest_order_bit_s(unsigned short n)
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
- return n - (n >> 1);
+ return (unsigned short)(n - (n >> 1));
}
MINLINE float min_ff(float a, float b)
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 8cfe4706937..b558227fa94 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -27,7 +27,6 @@
* \ingroup bli
*/
-
#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -36,57 +35,62 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLI_strict_flags.h"
+
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
{
- int i;
- float f, p, q, t;
-
- if (s == 0.0f) {
- *r = v;
- *g = v;
- *b = v;
- }
- else {
+ if (s != 0.0f) {
+ float i, f, p;
h = (h - floorf(h)) * 6.0f;
- i = (int)floorf(h);
+ i = floorf(h);
f = h - i;
- p = v * (1.0f - s);
- q = v * (1.0f - (s * f));
- t = v * (1.0f - (s * (1.0f - f)));
-
- switch (i) {
- case 0:
- *r = v;
- *g = t;
- *b = p;
- break;
- case 1:
- *r = q;
- *g = v;
- *b = p;
- break;
- case 2:
- *r = p;
- *g = v;
- *b = t;
- break;
- case 3:
- *r = p;
- *g = q;
- *b = v;
- break;
- case 4:
- *r = t;
- *g = p;
- *b = v;
- break;
- case 5:
- *r = v;
- *g = p;
- *b = q;
- break;
+
+ /* avoid computing q/t when not needed */
+ p = (v * (1.0f - s));
+#define q (v * (1.0f - (s * f)))
+#define t (v * (1.0f - (s * (1.0f - f))))
+
+ /* faster to compare floats then int conversion */
+ if (i < 1.0f) {
+ *r = v;
+ *g = t;
+ *b = p;
+ }
+ else if (i < 2.0f) {
+ *r = q;
+ *g = v;
+ *b = p;
+ }
+ else if (i < 3.0f) {
+ *r = p;
+ *g = v;
+ *b = t;
+ }
+ else if (i < 4.0f) {
+ *r = p;
+ *g = q;
+ *b = v;
+ }
+ else if (i < 5.0f) {
+ *r = t;
+ *g = p;
+ *b = v;
}
+ else {
+ *r = v;
+ *g = p;
+ *b = q;
+ }
+
+#undef q
+#undef t
+
+ }
+ else {
+ *r = v;
+ *g = v;
+ *b = v;
}
}
@@ -213,9 +217,9 @@ void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
return;
}
- *r = ri * (1.0f / 255.0f);
- *g = gi * (1.0f / 255.0f);
- *b = bi * (1.0f / 255.0f);
+ *r = (float)ri * (1.0f / 255.0f);
+ *g = (float)gi * (1.0f / 255.0f);
+ *b = (float)bi * (1.0f / 255.0f);
CLAMP(*r, 0.0f, 1.0f);
CLAMP(*g, 0.0f, 1.0f);
CLAMP(*b, 0.0f, 1.0f);
@@ -224,8 +228,7 @@ void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
{
float h, s, v;
- float cmax, cmin, cdelta;
- float rc, gc, bc;
+ float cmax, cmin;
cmax = r;
cmin = r;
@@ -235,37 +238,45 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
cmin = (b < cmin ? b : cmin);
v = cmax; /* value */
- if (cmax != 0.0f)
- s = (cmax - cmin) / cmax;
- else {
- s = 0.0f;
- }
- if (s == 0.0f)
- h = -1.0f;
- else {
- cdelta = cmax - cmin;
- rc = (cmax - r) / cdelta;
- gc = (cmax - g) / cdelta;
- bc = (cmax - b) / cdelta;
+ if (cmax != 0.0f) {
+ float cdelta;
- if (r == cmax) {
- h = bc - gc;
- }
- else if (g == cmax) {
- h = 2.0f + rc - bc;
+ cdelta = cmax - cmin;
+ s = cdelta / cmax;
+
+ if (s != 0.0f) {
+ float rc, gc, bc;
+
+ rc = (cmax - r) / cdelta;
+ gc = (cmax - g) / cdelta;
+ bc = (cmax - b) / cdelta;
+
+ if (r == cmax) {
+ h = bc - gc;
+ if (h < 0.0f) {
+ h += 6.0f;
+ }
+ }
+ else if (g == cmax) {
+ h = 2.0f + rc - bc;
+ }
+ else {
+ h = 4.0f + gc - rc;
+ }
+
+ h *= (1.0f / 6.0f);
}
else {
- h = 4.0f + gc - rc;
+ h = 0.0f;
}
-
- h = h * 60.0f;
- if (h < 0.0f)
- h += 360.0f;
+ }
+ else {
+ h = 0.0f;
+ s = 0.0f;
}
+ *lh = h;
*ls = s;
- *lh = h / 360.0f;
- if (*lh < 0.0f) *lh = 0.0f;
*lv = v;
}
@@ -365,15 +376,15 @@ void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int
unsigned int hsv_to_cpack(float h, float s, float v)
{
- short r, g, b;
+ unsigned int r, g, b;
float rf, gf, bf;
unsigned int col;
hsv_to_rgb(h, s, v, &rf, &gf, &bf);
- r = (short) (rf * 255.0f);
- g = (short) (gf * 255.0f);
- b = (short) (bf * 255.0f);
+ r = (unsigned int) (rf * 255.0f);
+ g = (unsigned int) (gf * 255.0f);
+ b = (unsigned int) (bf * 255.0f);
col = (r + (g * 256) + (b * 256 * 256));
return col;
@@ -381,17 +392,15 @@ unsigned int hsv_to_cpack(float h, float s, float v)
unsigned int rgb_to_cpack(float r, float g, float b)
{
- int ir, ig, ib;
+ unsigned int ir, ig, ib;
+
+ ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f));
+ ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f));
+ ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f));
- ir = (int)floor(255.0f * r);
- if (ir < 0) ir = 0;
- else if (ir > 255) ir = 255;
- ig = (int)floor(255.0f * g);
- if (ig < 0) ig = 0;
- else if (ig > 255) ig = 255;
- ib = (int)floor(255.0f * b);
- if (ib < 0) ib = 0;
- else if (ib > 255) ib = 255;
+ if (ir > 255) ir = 255;
+ if (ig > 255) ig = 255;
+ if (ib > 255) ib = 255;
return (ir + (ig * 256) + (ib * 256 * 256));
}
@@ -601,14 +610,14 @@ static float index_to_float(const unsigned short i)
void BLI_init_srgb_conversion(void)
{
static int initialized = 0;
- int i, b;
+ unsigned int i, b;
if (initialized) return;
initialized = 1;
/* Fill in the lookup table to convert floats to bytes: */
for (i = 0; i < 0x10000; i++) {
- float f = linearrgb_to_srgb(index_to_float(i)) * 255.0f;
+ float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f;
if (f <= 0) BLI_color_to_srgb_table[i] = 0;
else if (f < 255) BLI_color_to_srgb_table[i] = (unsigned short) (f * 0x100 + 0.5f);
else BLI_color_to_srgb_table[i] = 0xff00;
@@ -620,13 +629,13 @@ void BLI_init_srgb_conversion(void)
BLI_color_from_srgb_table[b] = f;
i = hipart(f);
/* replace entries so byte->float->byte does not change the data: */
- BLI_color_to_srgb_table[i] = b * 0x100;
+ BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100);
}
}
static float inverse_srgb_companding(float v)
{
if (v > 0.04045f) {
- return powf((v + 0.055f) / 1.055f, 2.4);
+ return powf((v + 0.055f) / 1.055f, 2.4f);
}
else {
return v / 12.92f;
@@ -650,7 +659,7 @@ static float xyz_to_lab_component(float v)
const float k = 903.3f;
if (v > eps) {
- return pow(v, 1.0f / 3.0f);
+ return powf(v, 1.0f / 3.0f);
}
else {
return (k * v + 16.0f) / 116.0f;
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 52947fcee08..4810fe757fa 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -60,10 +60,10 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1
tmp[2] = (mt * src1[3] * src1[2]) + (t * 255 * src2[2]);
tmp[3] = (mt * src1[3]) + (t * 255);
- dst[0] = divide_round_i(tmp[0], tmp[3]);
- dst[1] = divide_round_i(tmp[1], tmp[3]);
- dst[2] = divide_round_i(tmp[2], tmp[3]);
- dst[3] = divide_round_i(tmp[3], 255);
+ dst[0] = (unsigned char)divide_round_i(tmp[0], tmp[3]);
+ dst[1] = (unsigned char)divide_round_i(tmp[1], tmp[3]);
+ dst[2] = (unsigned char)divide_round_i(tmp[2], tmp[3]);
+ dst[3] = (unsigned char)divide_round_i(tmp[3], 255);
}
else {
/* no op */
@@ -85,9 +85,9 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1
tmp[1] = (src1[1] * 255) + (src2[1] * t);
tmp[2] = (src1[2] * 255) + (src2[2] * t);
- dst[0] = min_ii(divide_round_i(tmp[0], 255), 255);
- dst[1] = min_ii(divide_round_i(tmp[1], 255), 255);
- dst[2] = min_ii(divide_round_i(tmp[2], 255), 255);
+ dst[0] = (unsigned char)min_ii(divide_round_i(tmp[0], 255), 255);
+ dst[1] = (unsigned char)min_ii(divide_round_i(tmp[1], 255), 255);
+ dst[2] = (unsigned char)min_ii(divide_round_i(tmp[2], 255), 255);
dst[3] = src1[3];
}
else {
@@ -110,9 +110,9 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1
tmp[1] = (src1[1] * 255) - (src2[1] * t);
tmp[2] = (src1[2] * 255) - (src2[2] * t);
- dst[0] = max_ii(divide_round_i(tmp[0], 255), 0);
- dst[1] = max_ii(divide_round_i(tmp[1], 255), 0);
- dst[2] = max_ii(divide_round_i(tmp[2], 255), 0);
+ dst[0] = (unsigned char)max_ii(divide_round_i(tmp[0], 255), 0);
+ dst[1] = (unsigned char)max_ii(divide_round_i(tmp[1], 255), 0);
+ dst[2] = (unsigned char)max_ii(divide_round_i(tmp[2], 255), 0);
dst[3] = src1[3];
}
else {
@@ -136,9 +136,9 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1
tmp[1] = (mt * src1[1] * 255) + (t * src1[1] * src2[1]);
tmp[2] = (mt * src1[2] * 255) + (t * src1[2] * src2[2]);
- dst[0] = divide_round_i(tmp[0], 255 * 255);
- dst[1] = divide_round_i(tmp[1], 255 * 255);
- dst[2] = divide_round_i(tmp[2], 255 * 255);
+ dst[0] = (unsigned char)divide_round_i(tmp[0], 255 * 255);
+ dst[1] = (unsigned char)divide_round_i(tmp[1], 255 * 255);
+ dst[2] = (unsigned char)divide_round_i(tmp[2], 255 * 255);
dst[3] = src1[3];
}
else {
@@ -162,9 +162,9 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
tmp[1] = (mt * src1[1]) + (t * max_ii(src1[1], src2[1]));
tmp[2] = (mt * src1[2]) + (t * max_ii(src1[2], src2[2]));
- dst[0] = divide_round_i(tmp[0], 255);
- dst[1] = divide_round_i(tmp[1], 255);
- dst[2] = divide_round_i(tmp[2], 255);
+ dst[0] = (unsigned char)divide_round_i(tmp[0], 255);
+ dst[1] = (unsigned char)divide_round_i(tmp[1], 255);
+ dst[2] = (unsigned char)divide_round_i(tmp[2], 255);
dst[3] = src1[3];
}
else {
@@ -188,9 +188,9 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char s
tmp[1] = (mt * src1[1]) + (t * min_ii(src1[1], src2[1]));
tmp[2] = (mt * src1[2]) + (t * min_ii(src1[2], src2[2]));
- dst[0] = divide_round_i(tmp[0], 255);
- dst[1] = divide_round_i(tmp[1], 255);
- dst[2] = divide_round_i(tmp[2], 255);
+ dst[0] = (unsigned char)divide_round_i(tmp[0], 255);
+ dst[1] = (unsigned char)divide_round_i(tmp[1], 255);
+ dst[2] = (unsigned char)divide_round_i(tmp[2], 255);
dst[3] = src1[3];
}
else {
@@ -211,7 +211,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned c
dst[0] = src1[0];
dst[1] = src1[1];
dst[2] = src1[2];
- dst[3] = max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0);
+ dst[3] = (unsigned char)max_ii(src1[3] - divide_round_i(t * src2[3], 255), 0);
}
else {
/* no op */
@@ -231,7 +231,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned cha
dst[0] = src1[0];
dst[1] = src1[1];
dst[2] = src1[2];
- dst[3] = min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255);
+ dst[3] = (unsigned char)min_ii(src1[3] + divide_round_i(t * src2[3], 255), 255);
}
else {
/* no op */
@@ -251,10 +251,10 @@ MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned c
int tmp = (mt * src1[3] + t * src2[3]);
if (tmp > 0) {
- dst[0] = divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp);
- dst[1] = divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp);
- dst[2] = divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp);
- dst[3] = divide_round_i(tmp, 255);
+ dst[0] = (unsigned char)divide_round_i(mt * src1[0] * src1[3] + t * src2[0] * src2[3], tmp);
+ dst[1] = (unsigned char)divide_round_i(mt * src1[1] * src1[3] + t * src2[1] * src2[3], tmp);
+ dst[2] = (unsigned char)divide_round_i(mt * src1[2] * src1[3] + t * src2[2] * src2[3], tmp);
+ dst[3] = (unsigned char)divide_round_i(tmp, 255);
}
else {
dst[0] = src1[0];
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 4af1307c521..bb2201541d9 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -173,10 +173,6 @@ MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned
srgb_to_linearrgb_predivide_v4(linear, fsrgb);
}
-/* color macros for themes */
-#define rgba_char_args_set_fl(col, r, g, b, a) \
- rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
-
MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a)
{
col[0] = r;
@@ -228,7 +224,9 @@ MINLINE float rgb_to_grayscale(const float rgb[3])
MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
{
- return (76 * (unsigned short) rgb[0] + 148 * (unsigned short) rgb[1] + 31 * (unsigned short) rgb[2]) / 255;
+ return (unsigned char)(((76 * (unsigned short)rgb[0]) +
+ (148 * (unsigned short)rgb[1]) +
+ (31 * (unsigned short)rgb[2])) / 255);
}
/* luma from defined by 'YCC_JFIF', see #rgb_to_ycc */
@@ -239,7 +237,9 @@ MINLINE float rgb_to_luma(const float rgb[3])
MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3])
{
- return (76 * (unsigned short) rgb[0] + 150 * (unsigned short) rgb[1] + 29 * (unsigned short) rgb[2]) / 255;
+ return (unsigned char)(((76 * (unsigned short)rgb[0]) +
+ (150 * (unsigned short)rgb[1]) +
+ (29 * (unsigned short)rgb[2])) / 255);
}
/* gamma-corrected RGB --> CIE XYZ
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 0d15eede9ea..11875722d27 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -27,14 +27,14 @@
* \ingroup bli
*/
-
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_utildefines.h"
+#include "BLI_strict_flags.h"
+
/********************************** Polygons *********************************/
void cent_tri_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3])
@@ -88,16 +88,6 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo
return normalize_v3(n);
}
-float area_tri_v2(const float v1[2], const float v2[2], const float v3[2])
-{
- return 0.5f * fabsf((v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]));
-}
-
-float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2])
-{
- return 0.5f * ((v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]));
-}
-
/* only convex Quadrilaterals */
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
@@ -157,30 +147,35 @@ float area_poly_v3(int nr, float verts[][3], const float normal[3])
area = 0.0f;
for (a = 0; a < nr; a++) {
area += (co_curr[px] - co_prev[px]) * (co_curr[py] + co_prev[py]);
- co_prev = verts[a];
- co_curr = verts[a + 1];
+ co_prev = co_curr;
+ co_curr += 3;
}
return fabsf(0.5f * area / max);
}
-float area_poly_v2(int nr, float verts[][2])
+float cross_poly_v2(int nr, float verts[][2])
{
int a;
- float area;
- float *co_curr, *co_prev;
+ float cross;
+ const float *co_curr, *co_prev;
/* The Trapezium Area Rule */
co_prev = verts[nr - 1];
co_curr = verts[0];
- area = 0.0f;
+ cross = 0.0f;
for (a = 0; a < nr; a++) {
- area += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]);
- co_prev = verts[a];
- co_curr = verts[a + 1];
+ cross += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]);
+ co_prev = co_curr;
+ co_curr += 2;
}
- return fabsf(0.5f * area);
+ return cross;
+}
+
+float area_poly_v2(int nr, float verts[][2])
+{
+ return fabsf(0.5f * cross_poly_v2(nr, verts));
}
/********************************* Planes **********************************/
@@ -326,7 +321,7 @@ float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
const float length = len_squared_v3(plane);
const float side = plane_point_side_v3(plane, pt);
const float fac = side / length;
- return copysign(length * (fac * fac), side);
+ return copysignf(length * (fac * fac), side);
}
/**
@@ -399,7 +394,7 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3],
/* Check if P in edge region of AB, if so return projection of P onto AB */
vc = d1 * d4 - d3 * d2;
if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
- float v = d1 / (d1 - d3);
+ v = d1 / (d1 - d3);
/* barycentric coordinates (1-v,v,0) */
madd_v3_v3v3fl(r, a, ab, v);
return;
@@ -416,7 +411,7 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3],
/* Check if P in edge region of AC, if so return projection of P onto AC */
vb = d5 * d2 - d1 * d6;
if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
- float w = d2 / (d2 - d6);
+ w = d2 / (d2 - d6);
/* barycentric coordinates (1-w,0,w) */
madd_v3_v3v3fl(r, a, ac, w);
return;
@@ -424,7 +419,7 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3],
/* Check if P in edge region of BC, if so return projection of P onto BC */
va = d3 * d6 - d5 * d4;
if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
- float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+ w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
/* barycentric coordinates (0,1-w,w) */
sub_v3_v3v3(r, c, b);
mul_v3_fl(r, w);
@@ -456,9 +451,9 @@ int isect_line_line_v2_int(const int v1[2], const int v2[2], const int v3[2], co
div = (float)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]));
if (div == 0.0f) return ISECT_LINE_LINE_COLINEAR;
- lambda = ((float)(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
+ lambda = (float)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
- mu = ((float)(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
+ mu = (float)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) {
if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) return ISECT_LINE_LINE_EXACT;
@@ -642,7 +637,7 @@ int isect_line_sphere_v3(const float l1[3], const float l2[3],
return 1;
}
else if (i > 0.0f) {
- const float i_sqrt = sqrt(i); /* avoid calc twice */
+ const float i_sqrt = sqrtf(i); /* avoid calc twice */
/* first intersection */
mu = (-b + i_sqrt) / (2.0f * a);
@@ -694,7 +689,7 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2],
return 1;
}
else if (i > 0.0f) {
- const float i_sqrt = sqrt(i); /* avoid calc twice */
+ const float i_sqrt = sqrtf(i); /* avoid calc twice */
/* first intersection */
mu = (-b + i_sqrt) / (2.0f * a);
@@ -752,9 +747,9 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsign
angletot = fabsf(angletot);
if (use_holes) {
- const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ const float nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
angletot -= nested * (float)(M_PI * 2.0);
- return (angletot > 4.0f) != (nested % 2);
+ return (angletot > 4.0f) != ((int)nested % 2);
}
else {
return (angletot > 4.0f);
@@ -800,9 +795,9 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsign
angletot = fabsf(angletot);
if (use_holes) {
- const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ const float nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
angletot -= nested * (float)(M_PI * 2.0);
- return (angletot > 4.0f) != (nested % 2);
+ return (angletot > 4.0f) != ((int)nested % 2);
}
else {
return (angletot > 4.0f);
@@ -2005,7 +2000,7 @@ void fill_poly_v2i_n(
/* originally by Darel Rex Finley, 2007 */
int nodes, pixel_y, i, j, swap;
- int *node_x = MEM_mallocN(sizeof(*node_x) * (nr + 1), __func__);
+ int *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(nr + 1), __func__);
/* Loop through the rows of the image. */
for (pixel_y = ymin; pixel_y < ymax; pixel_y++) {
@@ -2381,7 +2376,7 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3],
/* given an array with some invalid values this function interpolates valid values
* replacing the invalid ones */
-int interp_sparse_array(float *array, int const list_size, const float skipval)
+int interp_sparse_array(float *array, const int list_size, const float skipval)
{
int found_invalid = 0;
int found_valid = 0;
@@ -2405,11 +2400,11 @@ int interp_sparse_array(float *array, int const list_size, const float skipval)
float valid_last = skipval;
int valid_ofs = 0;
- float *array_up = MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up");
- float *array_down = MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up");
+ float *array_up = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up");
+ float *array_down = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up");
- int *ofs_tot_up = MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tup");
- int *ofs_tot_down = MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tdown");
+ int *ofs_tot_up = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tup");
+ int *ofs_tot_down = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tdown");
for (i = 0; i < list_size; i++) {
if (array[i] == skipval) {
@@ -2440,7 +2435,8 @@ int interp_sparse_array(float *array, int const list_size, const float skipval)
for (i = 0; i < list_size; i++) {
if (array[i] == skipval) {
if (array_up[i] != skipval && array_down[i] != skipval) {
- array[i] = ((array_up[i] * ofs_tot_down[i]) + (array_down[i] * ofs_tot_up[i])) / (float)(ofs_tot_down[i] + ofs_tot_up[i]);
+ array[i] = ((array_up[i] * (float)ofs_tot_down[i]) +
+ (array_down[i] * (float)ofs_tot_up[i])) / (float)(ofs_tot_down[i] + ofs_tot_up[i]);
}
else if (array_up[i] != skipval) {
array[i] = array_up[i];
@@ -2690,6 +2686,13 @@ void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const
/* bilinear reverse */
void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
{
+ resolve_quad_uv_deriv(r_uv, NULL, st, st0, st1, st2, st3);
+}
+
+/* bilinear reverse with derivatives */
+void resolve_quad_uv_deriv(float r_uv[2], float r_deriv[2][2],
+ const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
+{
const double signed_area = (st0[0] * st1[1] - st0[1] * st1[0]) + (st1[0] * st2[1] - st1[1] * st2[0]) +
(st2[0] * st3[1] - st2[1] * st3[0]) + (st3[0] * st0[1] - st3[1] * st0[0]);
@@ -2703,7 +2706,7 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const
/* C = (p1-p) X (p1-p2) */
const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]);
- const double denom = a - 2 * b + fC;
+ double denom = a - 2 * b + fC;
/* clear outputs */
zero_v2(r_uv);
@@ -2727,7 +2730,7 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const
const double denom_s = (1 - r_uv[0]) * (st0[0] - st3[0]) + r_uv[0] * (st1[0] - st2[0]);
const double denom_t = (1 - r_uv[0]) * (st0[1] - st3[1]) + r_uv[0] * (st1[1] - st2[1]);
int i = 0;
- double denom = denom_s;
+ denom = denom_s;
if (fabs(denom_s) < fabs(denom_t)) {
i = 1;
@@ -2737,6 +2740,31 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const
if (IS_ZERO(denom) == 0)
r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) + r_uv[0] * (st1[i] - st[i])) / denom);
}
+
+ if (r_deriv) {
+ float tmp1[2], tmp2[2], s[2], t[2];
+
+ /* clear outputs */
+ zero_v2(r_deriv[0]);
+ zero_v2(r_deriv[1]);
+
+ sub_v2_v2v2(tmp1, st1, st0);
+ sub_v2_v2v2(tmp2, st2, st3);
+ interp_v2_v2v2(s, tmp1, tmp2, r_uv[1]);
+ sub_v2_v2v2(tmp1, st3, st0);
+ sub_v2_v2v2(tmp2, st2, st1);
+ interp_v2_v2v2(t, tmp1, tmp2, r_uv[0]);
+
+ denom = t[0] * s[1] - t[1] * s[0];
+
+ if (!IS_ZERO(denom)) {
+ double inv_denom = 1.0 / denom;
+ r_deriv[0][0] = (float)((double)-t[1] * inv_denom);
+ r_deriv[0][1] = (float)((double) t[0] * inv_denom);
+ r_deriv[1][0] = (float)((double) s[1] * inv_denom);
+ r_deriv[1][1] = (float)((double)-s[0] * inv_denom);
+ }
+ }
}
#undef IS_ZERO
@@ -3071,7 +3099,6 @@ void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
/* accumulate angle weighted face normal */
{
const float *prev_edge = vdiffs[nverts - 1];
- int i;
for (i = 0; i < nverts; i++) {
const float *cur_edge = vdiffs[i];
@@ -3187,7 +3214,7 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
}
}
if (!weight || !rweight) {
- accu_weight = accu_rweight = list_size;
+ accu_weight = accu_rweight = (float)list_size;
}
mul_v3_fl(accu_com, 1.0f / accu_weight);
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index ac5c0033067..a5906dbdf6c 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -34,6 +34,23 @@
#include <string.h>
+/********************************** Polygons *********************************/
+
+MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2])
+{
+ return (v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]);
+}
+
+MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2])
+{
+ return 0.5f * ((v1[0] - v2[0]) * (v2[1] - v3[1]) + (v1[1] - v2[1]) * (v3[0] - v2[0]));
+}
+
+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));
+}
+
/****************************** Spherical Harmonics **************************/
MINLINE void zero_sh(float r[9])
@@ -62,7 +79,7 @@ MINLINE void add_sh_shsh(float r[9], const float a[9], const float b[9])
r[i] = a[i] + b[i];
}
-MINLINE float dot_shsh(float a[9], float b[9])
+MINLINE float dot_shsh(const float a[9], const float b[9])
{
float r = 0.0f;
int i;
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index d1acd45e40e..9af1c8677df 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -34,6 +34,8 @@
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
/**************************************************************************
* INTERPOLATIONS
*
@@ -105,13 +107,17 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const fl
/* sample area entirely outside image? */
if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) {
+ if (float_output)
+ float_output[0] = float_output[1] = float_output[2] = float_output[3] = 0.0f;
+ if (byte_output)
+ byte_output[0] = byte_output[1] = byte_output[2] = byte_output[3] = 0;
return;
}
i = (int)floor(u);
j = (int)floor(v);
- a = u - i;
- b = v - j;
+ a = u - (float)i;
+ b = v - (float)j;
zero_v4(out);
@@ -126,7 +132,7 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const fl
for (n = -1; n <= 2; n++) {
x1 = i + n;
CLAMP(x1, 0, width - 1);
- wx = P(n - a);
+ wx = P((float)n - a);
for (m = -1; m <= 2; m++) {
float data[4];
@@ -219,18 +225,18 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const fl
}
else {
if (components == 1) {
- byte_output[0] = out[0] + 0.5f;
+ byte_output[0] = (unsigned char)(out[0] + 0.5f);
}
else if (components == 3) {
- byte_output[0] = out[0] + 0.5f;
- byte_output[1] = out[1] + 0.5f;
- byte_output[2] = out[2] + 0.5f;
+ byte_output[0] = (unsigned char)(out[0] + 0.5f);
+ byte_output[1] = (unsigned char)(out[1] + 0.5f);
+ byte_output[2] = (unsigned char)(out[2] + 0.5f);
}
else {
- byte_output[0] = out[0] + 0.5f;
- byte_output[1] = out[1] + 0.5f;
- byte_output[2] = out[2] + 0.5f;
- byte_output[3] = out[3] + 0.5f;
+ byte_output[0] = (unsigned char)(out[0] + 0.5f);
+ byte_output[1] = (unsigned char)(out[1] + 0.5f);
+ byte_output[2] = (unsigned char)(out[2] + 0.5f);
+ byte_output[3] = (unsigned char)(out[3] + 0.5f);
}
}
}
@@ -263,15 +269,16 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f
y1 = (int)floor(v);
y2 = (int)ceil(v);
- /* sample area entirely outside image? */
- if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) {
- return;
- }
-
if (float_output) {
const float *row1, *row2, *row3, *row4;
float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* sample area entirely outside image? */
+ if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) {
+ float_output[0] = float_output[1] = float_output[2] = float_output[3] = 0.0f;
+ return;
+ }
+
/* sample including outside of edges of image */
if (x1 < 0 || y1 < 0) row1 = empty;
else row1 = float_buffer + width * y1 * components + components * x1;
@@ -308,6 +315,12 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f
const unsigned char *row1, *row2, *row3, *row4;
unsigned char empty[4] = {0, 0, 0, 0};
+ /* sample area entirely outside image? */
+ if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) {
+ byte_output[0] = byte_output[1] = byte_output[2] = byte_output[3] = 0;
+ return;
+ }
+
/* sample including outside of edges of image */
if (x1 < 0 || y1 < 0) row1 = empty;
else row1 = byte_buffer + width * y1 * components + components * x1;
@@ -326,18 +339,18 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const f
a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b);
if (components == 1) {
- byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f;
+ byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f);
}
else if (components == 3) {
- byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f;
- byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f;
- byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f;
+ byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f);
+ byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f);
+ byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f);
}
else {
- byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f;
- byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f;
- byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f;
- byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3] + 0.5f;
+ byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + 0.5f);
+ byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + 0.5f);
+ byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + 0.5f);
+ byte_output[3] = (unsigned char)(ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3] + 0.5f);
}
}
}
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 1f52caac8e9..a4ea406ed43 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -31,6 +31,8 @@
#include <assert.h>
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
/********************************* Init **************************************/
void zero_m3(float m[3][3])
@@ -115,17 +117,17 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
void copy_m3_m3d(float R[3][3], double A[3][3])
{
/* Keep it stupid simple for better data flow in CPU. */
- R[0][0] = A[0][0];
- R[0][1] = A[0][1];
- R[0][2] = A[0][2];
+ R[0][0] = (float)A[0][0];
+ R[0][1] = (float)A[0][1];
+ R[0][2] = (float)A[0][2];
- R[1][0] = A[1][0];
- R[1][1] = A[1][1];
- R[1][2] = A[1][2];
+ R[1][0] = (float)A[1][0];
+ R[1][1] = (float)A[1][1];
+ R[1][2] = (float)A[1][2];
- R[2][0] = A[2][0];
- R[2][1] = A[2][1];
- R[2][2] = A[2][2];
+ R[2][0] = (float)A[2][0];
+ R[2][1] = (float)A[2][1];
+ R[2][2] = (float)A[2][2];
}
void swap_m3m3(float m1[3][3], float m2[3][3])
@@ -711,11 +713,11 @@ int invert_m4_m4(float inverse[4][4], float mat[4][4])
for (i = 0; i < 4; i++) {
/* Look for row with max pivot */
- max = fabs(tempmat[i][i]);
+ max = fabsf(tempmat[i][i]);
maxj = i;
for (j = i + 1; j < 4; j++) {
if (fabsf(tempmat[j][i]) > max) {
- max = fabs(tempmat[j][i]);
+ max = fabsf(tempmat[j][i]);
maxj = j;
}
}
@@ -988,7 +990,7 @@ bool is_orthogonal_m4(float m[4][4])
for (i = 0; i < 4; i++) {
for (j = 0; j < i; j++) {
- if (fabsf(dot_vn_vn(m[i], m[j], 4)) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON)
return 0;
}
@@ -1018,7 +1020,7 @@ bool is_orthonormal_m4(float m[4][4])
int i;
for (i = 0; i < 4; i++)
- if (fabsf(dot_vn_vn(m[i], m[i], 4) - 1) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
return 0;
return 1;
@@ -1029,7 +1031,7 @@ bool is_orthonormal_m4(float m[4][4])
bool is_uniform_scaled_m3(float m[3][3])
{
- const float eps = 1e-7;
+ const float eps = 1e-7f;
float t[3][3];
float l1, l2, l3, l4, l5, l6;
@@ -1626,7 +1628,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
int m = 4;
int n = 4;
int maxiter = 200;
- int nu = min_ff(m, n);
+ int nu = min_ii(m, n);
float *work = work1;
float *e = work2;
@@ -1637,14 +1639,14 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
/* Reduce A to bidiagonal form, storing the diagonal elements
* in s and the super-diagonal elements in e. */
- int nct = min_ff(m - 1, n);
- int nrt = max_ff(0, min_ff(n - 2, m));
+ int nct = min_ii(m - 1, n);
+ int nrt = max_ii(0, min_ii(n - 2, m));
copy_m4_m4(A, A_);
zero_m4(U);
zero_v4(s);
- for (k = 0; k < max_ff(nct, nrt); k++) {
+ for (k = 0; k < max_ii(nct, nrt); k++) {
if (k < nct) {
/* Compute the transformation for the k-th column and
@@ -1748,7 +1750,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
/* Set up the final bidiagonal matrix or order p. */
- p = min_ff(n, m + 1);
+ p = min_ii(n, m + 1);
if (nct < n) {
s[nct] = A[nct][nct];
}
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 41535cf32b6..536b4d79385 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -27,11 +27,11 @@
* \ingroup bli
*/
-
-
#include <assert.h>
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
/******************************** Quaternions ********************************/
/* used to test is a quat is not normalized (only used for debug prints) */
@@ -444,7 +444,7 @@ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
/* rotate to axis */
if (axis > 2) {
copy_v3_v3(tvec, vec);
- axis -= 3;
+ axis = (short)(axis - 3);
}
else {
negate_v3_v3(tvec, vec);
@@ -1183,10 +1183,10 @@ void eulO_to_quat(float q[4], const float e[3], const short order)
a[j] = cj * ss + sj * cc;
a[k] = cj * cs - sj * sc;
- q[0] = cj * cc + sj * ss;
- q[1] = a[0];
- q[2] = a[1];
- q[3] = a[2];
+ q[0] = (float)(cj * cc + sj * ss);
+ q[1] = (float)(a[0]);
+ q[2] = (float)(a[1]);
+ q[3] = (float)(a[2]);
if (R->parity) q[j + 1] = -q[j + 1];
}
@@ -1230,15 +1230,15 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order)
sc = si * ch;
ss = si * sh;
- M[i][i] = cj * ch;
- M[j][i] = sj * sc - cs;
- M[k][i] = sj * cc + ss;
- M[i][j] = cj * sh;
- M[j][j] = sj * ss + cc;
- M[k][j] = sj * cs - sc;
- M[i][k] = -sj;
- M[j][k] = cj * si;
- M[k][k] = cj * ci;
+ M[i][i] = (float)(cj * ch);
+ M[j][i] = (float)(sj * sc - cs);
+ M[k][i] = (float)(sj * cc + ss);
+ M[i][j] = (float)(cj * sh);
+ M[j][j] = (float)(sj * ss + cc);
+ M[k][j] = (float)(sj * cs - sc);
+ M[i][k] = (float)(-sj);
+ M[j][k] = (float)(cj * si);
+ M[k][k] = (float)(cj * ci);
}
/* returns two euler calculation methods, so we can pick the best */
@@ -1256,17 +1256,17 @@ static void mat3_to_eulo2(float M[3][3], float e1[3], float e2[3], const short o
cy = sqrt(m[i][i] * m[i][i] + m[i][j] * m[i][j]);
if (cy > 16.0 * (double)FLT_EPSILON) {
- e1[i] = atan2(m[j][k], m[k][k]);
- e1[j] = atan2(-m[i][k], cy);
- e1[k] = atan2(m[i][j], m[i][i]);
+ e1[i] = atan2f(m[j][k], m[k][k]);
+ e1[j] = atan2f(-m[i][k], (float)cy);
+ e1[k] = atan2f(m[i][j], m[i][i]);
- e2[i] = atan2(-m[j][k], -m[k][k]);
- e2[j] = atan2(-m[i][k], -cy);
- e2[k] = atan2(-m[i][j], -m[i][i]);
+ e2[i] = atan2f(-m[j][k], -m[k][k]);
+ e2[j] = atan2f(-m[i][k], (float)-cy);
+ e2[k] = atan2f(-m[i][j], -m[i][i]);
}
else {
- e1[i] = atan2(-m[k][j], m[j][j]);
- e1[j] = atan2(-m[i][k], cy);
+ e1[i] = atan2f(-m[k][j], m[j][j]);
+ e1[j] = atan2f(-m[i][k], (float)cy);
e1[k] = 0;
copy_v3_v3(e2, e1);
@@ -1632,13 +1632,14 @@ void copy_dq_dq(DualQuat *dq1, const DualQuat *dq2)
void quat_apply_track(float quat[4], short axis, short upflag)
{
/* rotations are hard coded to match vec_to_quat */
+ const float sqrt_1_2 = (float)M_SQRT1_2;
const float quat_track[][4] = {
- {M_SQRT1_2, 0.0, -M_SQRT1_2, 0.0}, /* pos-y90 */
+ {sqrt_1_2, 0.0, -sqrt_1_2, 0.0}, /* pos-y90 */
{0.5, 0.5, 0.5, 0.5}, /* Quaternion((1,0,0), radians(90)) * Quaternion((0,1,0), radians(90)) */
- {M_SQRT1_2, 0.0, 0.0, M_SQRT1_2}, /* pos-z90 */
- {M_SQRT1_2, 0.0, M_SQRT1_2, 0.0}, /* neg-y90 */
+ {sqrt_1_2, 0.0, 0.0, sqrt_1_2}, /* pos-z90 */
+ {sqrt_1_2, 0.0, sqrt_1_2, 0.0}, /* neg-y90 */
{0.5, -0.5, -0.5, 0.5}, /* Quaternion((1,0,0), radians(-90)) * Quaternion((0,1,0), radians(-90)) */
- {0.0, M_SQRT1_2, M_SQRT1_2, 0.0} /* no rotation */
+ {0.0, sqrt_1_2, sqrt_1_2, 0.0} /* no rotation */
};
assert(axis >= 0 && axis <= 5);
@@ -1646,15 +1647,16 @@ void quat_apply_track(float quat[4], short axis, short upflag)
mul_qt_qtqt(quat, quat, quat_track[axis]);
- if (axis > 2)
- axis = axis - 3;
+ if (axis > 2) {
+ axis = (short)(axis - 3);
+ }
/* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first
* up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d
* the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */
if (upflag != (2 - axis) >> 1) {
- float q[4] = {M_SQRT1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */
- q[axis + 1] = ((axis == 1)) ? M_SQRT1_2 : -M_SQRT1_2; /* flip non Y axis */
+ float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */
+ q[axis + 1] = ((axis == 1)) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */
mul_qt_qtqt(quat, quat, q);
}
}
@@ -1835,7 +1837,7 @@ static int _axis_convert_lut[23][24] = {
// _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
-MINLINE int _axis_signed(const int axis)
+BLI_INLINE int _axis_signed(const int axis)
{
return (axis < 3) ? axis : axis - 3;
}
@@ -1849,7 +1851,7 @@ int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int
{
// from functools import reduce
int value;
- int i;
+ unsigned int i;
if (from_forward == to_forward && from_up == to_up) {
unit_m3(r_mat);
@@ -1870,8 +1872,8 @@ int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int
(to_up << (3 * 3)));
for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
- int j;
- for (j = 0; j < sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0]); j++) {
+ unsigned int j;
+ for (j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) {
if (_axis_convert_lut[i][j] == value) {
copy_m3_m3(r_mat, _axis_convert_matrix[i]);
return true;
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index ba0394dbc66..48134cbf21d 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -27,10 +27,10 @@
* \ingroup bli
*/
-
-
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
//******************************* Interpolation *******************************/
void interp_v2_v2v2(float target[2], const float a[2], const float b[2], const float t)
@@ -497,8 +497,8 @@ void ortho_basis_v3v3_v3(float v1[3], float v2[3], const float v[3])
*/
void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
{
- const float costheta = cos(angle);
- const float sintheta = sin(angle);
+ const float costheta = cosf(angle);
+ const float sintheta = sinf(angle);
/* double check they are normalized */
BLI_ASSERT_UNIT_V3(axis);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index ace8e6b48c1..45a0cb3f8e2 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -236,6 +236,12 @@ MINLINE void swap_v4_v4(float a[4], float b[4])
}
/* float args -> vec */
+MINLINE void copy_v2_fl2(float v[2], float x, float y)
+{
+ v[0] = x;
+ v[1] = y;
+}
+
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
{
v[0] = x;
@@ -574,9 +580,9 @@ MINLINE void negate_v4_v4(float r[4], const float a[4])
/* could add more... */
MINLINE void negate_v3_short(short r[3])
{
- r[0] = -r[0];
- r[1] = -r[1];
- r[2] = -r[2];
+ r[0] = (short)-r[0];
+ r[1] = (short)-r[1];
+ r[2] = (short)-r[2];
}
MINLINE float dot_v2v2(const float a[2], const float b[2])
@@ -589,6 +595,11 @@ 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_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];
+}
+
MINLINE float cross_v2v2(const float a[2], const float b[2])
{
return a[0] * b[1] - a[1] * b[0];
@@ -643,7 +654,7 @@ MINLINE float len_manhattan_v2(const float v[2])
MINLINE int len_manhattan_v2_int(const int v[2])
{
- return ABS(v[0]) + ABS(v[1]);
+ return abs(v[0]) + abs(v[1]);
}
MINLINE float len_manhattan_v3(const float v[3])
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index d323098827b..a753975ef7c 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -89,18 +89,18 @@ static char btempdir[FILE_MAX]; /* temporary directory */
*/
int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
{
- unsigned short nums = 0, nume = 0;
- short i;
+ unsigned int nums = 0, nume = 0;
+ int i;
bool found_digit = false;
const char * const lslash = BLI_last_slash(string);
- const unsigned short string_len = strlen(string);
- const unsigned short lslash_len = lslash != NULL ? (int)(lslash - string) : 0;
- unsigned short name_end = string_len;
+ const unsigned int string_len = strlen(string);
+ const unsigned int lslash_len = lslash != NULL ? (int)(lslash - string) : 0;
+ unsigned int name_end = string_len;
while (name_end > lslash_len && string[--name_end] != '.') {} /* name ends at dot if present */
if (name_end == lslash_len && string[name_end] != '.') name_end = string_len;
- for (i = name_end - 1; i >= lslash_len; i--) {
+ for (i = name_end - 1; i >= (int)lslash_len; i--) {
if (isdigit(string[i])) {
if (found_digit) {
nums = i;
@@ -229,7 +229,7 @@ void BLI_newname(char *name, int add)
* \return true if there if the name was changed
*/
bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
- void *arg, const char *defname, char delim, char *name, short name_len)
+ void *arg, const char *defname, char delim, char *name, int name_len)
{
if (name[0] == '\0') {
BLI_strncpy(name, defname, name_len);
@@ -281,13 +281,13 @@ bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
* defname: the name that should be used by default if none is specified already
* delim: the character which acts as a delimiter between parts of the name
*/
-static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
+static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs)
{
Link *link;
for (link = list->first; link; link = link->next) {
if (link != vlink) {
- if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
+ if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
return true;
}
}
@@ -298,7 +298,7 @@ static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name,
static bool uniquename_unique_check(void *arg, const char *name)
{
- struct {ListBase *lb; void *vlink; short name_offs; } *data = arg;
+ struct {ListBase *lb; void *vlink; int name_offs; } *data = arg;
return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
}
@@ -313,9 +313,9 @@ static bool uniquename_unique_check(void *arg, const char *name)
* \param name_offs Offset of name within block structure
* \param name_len Maximum length of name area
*/
-void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, short name_offs, short name_len)
+void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int name_len)
{
- struct {ListBase *lb; void *vlink; short name_offs; } data;
+ struct {ListBase *lb; void *vlink; int name_offs; } data;
data.lb = list;
data.vlink = vlink;
data.name_offs = name_offs;
@@ -622,7 +622,7 @@ bool BLI_parent_dir(char *path)
*/
static bool stringframe_chars(const char *path, int *char_start, int *char_end)
{
- int ch_sta, ch_end, i;
+ unsigned int ch_sta, ch_end, i;
/* Insert current frame: file### -> file001 */
ch_sta = ch_end = 0;
for (i = 0; path[i] != '\0'; i++) {
@@ -720,6 +720,15 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
}
/**
+ * Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
+ */
+bool BLI_path_frame_check_chars(const char *path)
+{
+ int ch_sta, ch_end; /* dummy args */
+ return stringframe_chars(path, &ch_sta, &ch_end);
+}
+
+/**
* If path begins with "//", strips that and replaces it with basepath directory. Also converts
* a drive-letter prefix to something more sensible if this is a non-drive-letter-based system.
* Returns true if "//" prefix expansion was done.
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
new file mode 100644
index 00000000000..287a0909870
--- /dev/null
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -0,0 +1,452 @@
+/*
+ * ***** 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.c
+ * \ingroup bli
+ *
+ * A simple implementation of the ear cutting algorithm
+ * to triangulate simple polygons without holes.
+ *
+ * \note
+ *
+ * Changes made for Blender.
+ *
+ * - loop the array to clip last verts first (less array resizing)
+ *
+ * - advance the ear to clip each iteration
+ * to avoid fan-filling convex shapes (USE_CLIP_EVEN).
+ *
+ * - avoid intersection tests when there are no convex points (USE_CONVEX_SKIP).
+ *
+ * \note
+ *
+ * No globals - keep threadsafe.
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BLI_memarena.h"
+#include "BLI_alloca.h"
+
+#include "BLI_polyfill2d.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+#define SIGN_EPS 0.000001f
+
+/* avoid fan-fill topology */
+#define USE_CLIP_EVEN
+#define USE_CONVEX_SKIP
+// #define USE_CONVEX_SKIP_TEST
+
+typedef signed char eSign;
+enum {
+ CONCAVE = -1,
+ TANGENTIAL = 0,
+ CONVEX = 1,
+};
+
+typedef struct PolyFill {
+ unsigned int *indices; /* vertex aligned */
+
+ const float (*coords)[2];
+ unsigned int coords_tot;
+ eSign *coords_sign;
+#ifdef USE_CONVEX_SKIP
+ unsigned int coords_tot_concave;
+#endif
+
+ /* A polygon with n vertices has a triangulation of n-2 triangles. */
+ unsigned int (*tris)[3];
+ unsigned int tris_tot;
+} PolyFill;
+
+
+/* based on libgdx 2013-11-28, apache 2.0 licensed */
+
+static eSign pf_coord_sign_calc(PolyFill *pf, unsigned int index);
+static unsigned int pf_index_prev(const PolyFill *pf, const unsigned int index);
+static unsigned int pf_index_next(const PolyFill *pf, unsigned index);
+
+#ifdef USE_CLIP_EVEN
+static unsigned int pf_ear_tip_find(PolyFill *pf, const unsigned int index_offset);
+#else
+static unsigned int pf_ear_tip_find(PolyFill *pf);
+#endif
+static bool pf_ear_tip_check(PolyFill *pf, const unsigned int index_ear_tip);
+static void pf_ear_tip_cut(PolyFill *pf, unsigned int index_ear_tip);
+
+
+BLI_INLINE eSign signum_i(float a)
+{
+ if (UNLIKELY(fabsf(a) < SIGN_EPS))
+ return 0;
+ else if (a > 0.0f)
+ return 1;
+ else
+ return -1;
+}
+
+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(v3, v2, v1));
+}
+
+static unsigned int *pf_tri_add(PolyFill *pf)
+{
+ return pf->tris[pf->tris_tot++];
+}
+
+static void pf_coord_remove(PolyFill *pf, const unsigned int index)
+{
+ ARRAY_DELETE(pf->indices, index, 1, pf->coords_tot);
+ ARRAY_DELETE(pf->coords_sign, index, 1, pf->coords_tot);
+ pf->coords_tot -= 1;
+}
+
+static void pf_triangulate(PolyFill *pf)
+{
+ /* localize */
+ eSign *coords_sign = pf->coords_sign;
+
+ unsigned int index_ear_tip = 0;
+
+
+ while (pf->coords_tot > 3) {
+ unsigned int i_prev, i_next;
+
+#ifdef USE_CONVEX_SKIP
+ eSign sign_orig_prev, sign_orig_next;
+#endif
+
+
+#ifdef USE_CLIP_EVEN
+ index_ear_tip = pf_ear_tip_find(pf, index_ear_tip);
+#else
+ index_ear_tip = pf_ear_tip_find(pf);
+#endif
+
+#ifdef USE_CONVEX_SKIP
+ if (coords_sign[index_ear_tip] != CONVEX) {
+ pf->coords_tot_concave -= 1;
+ }
+#endif
+
+ pf_ear_tip_cut(pf, index_ear_tip);
+
+ /* The type of the two vertices adjacent to the clipped vertex may have changed. */
+ i_prev = pf_index_prev(pf, index_ear_tip);
+ i_next = (index_ear_tip == pf->coords_tot) ? 0 : index_ear_tip;
+
+#ifdef USE_CONVEX_SKIP
+ sign_orig_prev = coords_sign[i_prev];
+ sign_orig_next = coords_sign[i_next];
+#endif
+
+ coords_sign[i_prev] = pf_coord_sign_calc(pf, i_prev);
+ coords_sign[i_next] = pf_coord_sign_calc(pf, i_next);
+
+#ifdef USE_CONVEX_SKIP
+ /* check if any verts became convex the (else if)
+ * case is highly unlikely but may happen with degenerate polygons */
+ if ((sign_orig_prev != CONVEX) && (coords_sign[i_prev] == CONVEX)) pf->coords_tot_concave -= 1;
+ else if (UNLIKELY((sign_orig_prev == CONVEX) && (coords_sign[i_prev] != CONVEX))) pf->coords_tot_concave += 1;
+
+ if ((sign_orig_next != CONVEX) && (coords_sign[i_next] == CONVEX)) pf->coords_tot_concave -= 1;
+ else if (UNLIKELY((sign_orig_next == CONVEX) && (coords_sign[i_next] != CONVEX))) pf->coords_tot_concave += 1;
+#endif
+
+#ifdef USE_CLIP_EVEN
+ index_ear_tip = i_prev;
+#endif
+ }
+
+ if (pf->coords_tot == 3) {
+ unsigned int *tri = pf_tri_add(pf);
+ tri[0] = pf->indices[0];
+ tri[1] = pf->indices[1];
+ tri[2] = pf->indices[2];
+ }
+}
+
+/**
+ * \return CONCAVE, TANGENTIAL or CONVEX
+ */
+static eSign pf_coord_sign_calc(PolyFill *pf, unsigned int index)
+{
+ /* localize */
+ unsigned int *indices = pf->indices;
+ const float (*coords)[2] = pf->coords;
+
+ return span_tri_v2_sign(
+ coords[indices[pf_index_prev(pf, index)]],
+ coords[indices[index]],
+ coords[indices[pf_index_next(pf, index)]]);
+}
+
+#ifdef USE_CLIP_EVEN
+static unsigned int pf_ear_tip_find(PolyFill *pf, const unsigned int index_offset)
+#else
+static unsigned int pf_ear_tip_find(PolyFill *pf)
+#endif
+{
+ /* localize */
+ const eSign *coords_sign = pf->coords_sign;
+ const unsigned int coords_tot = pf->coords_tot;
+
+ unsigned int i;
+
+
+ i = coords_tot;
+ while (i--) {
+#ifdef USE_CLIP_EVEN
+ unsigned int j = (i + index_offset) % coords_tot;
+ if (pf_ear_tip_check(pf, j)) {
+ return j;
+ }
+#else
+ if (pf_ear_tip_check(pf, i)) {
+ return i;
+ }
+#endif
+ }
+
+ /* Desperate mode: if no vertex is an ear tip, we are dealing with a degenerate polygon (e.g. nearly collinear).
+ * Note that the input was not necessarily degenerate, but we could have made it so by clipping some valid ears.
+ *
+ * Idea taken from Martin Held, "FIST: Fast industrial-strength triangulation of polygons", Algorithmica (1998),
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.115.291
+ *
+ * Return a convex or tangential vertex if one exists.
+ */
+
+ i = coords_tot;
+ while (i--) {
+#ifdef USE_CLIP_EVEN
+ unsigned int j = (i + index_offset) % coords_tot;
+ if (coords_sign[j] != CONCAVE) {
+ return j;
+ }
+#else
+ if (coords_sign[i] != CONCAVE) {
+ return i;
+ }
+#endif
+ }
+
+ /* If all vertices are concave, just return the last one. */
+ return coords_tot - 1;
+}
+
+static bool pf_ear_tip_check(PolyFill *pf, const unsigned int index_ear_tip)
+{
+ /* localize */
+ const unsigned int *indices = pf->indices;
+ const float (*coords)[2] = pf->coords;
+ const eSign *coords_sign = pf->coords_sign;
+
+ unsigned int i_prev, i_curr, i_next;
+
+ const float *v1, *v2, *v3;
+
+#ifdef USE_CONVEX_SKIP
+ unsigned int coords_tot_concave_checked = 0;
+#endif
+
+
+#ifdef USE_CONVEX_SKIP
+
+#ifdef USE_CONVEX_SKIP_TEST
+ /* check if counting is wrong */
+ {
+ unsigned int coords_tot_concave_test = 0;
+ unsigned int i = pf->coords_tot;
+ while (i--) {
+ if (coords_sign[i] != CONVEX) {
+ coords_tot_concave_test += 1;
+ }
+ }
+ BLI_assert(coords_tot_concave_test == pf->coords_tot_concave);
+ }
+#endif
+
+ /* fast-path for circles */
+ if (pf->coords_tot_concave == 0) {
+ return true;
+ }
+#endif
+
+ if (UNLIKELY(coords_sign[index_ear_tip] == CONCAVE)) {
+ return false;
+ }
+
+ i_prev = pf_index_prev(pf, index_ear_tip);
+ i_next = pf_index_next(pf, index_ear_tip);
+
+ v1 = coords[indices[i_prev]];
+ v2 = coords[indices[index_ear_tip]];
+ v3 = coords[indices[i_next]];
+
+ /* Check if any point is inside the triangle formed by previous, current and next vertices.
+ * Only consider vertices that are not part of this triangle, or else we'll always find one inside. */
+
+ for (i_curr = pf_index_next(pf, i_next); i_curr != i_prev; i_curr = pf_index_next(pf, i_curr)) {
+ /* Concave vertices can obviously be inside the candidate ear, but so can tangential vertices
+ * if they coincide with one of the triangle's vertices. */
+ if (coords_sign[i_curr] != CONVEX) {
+ const float *v = coords[indices[i_curr]];
+ /* Because the polygon has clockwise winding order,
+ * the area sign will be positive if the point is strictly inside.
+ * It will be 0 on the edge, which we want to include as well. */
+ if ((span_tri_v2_sign(v1, v2, v) == CONVEX) &&
+ (span_tri_v2_sign(v2, v3, v) == CONVEX) &&
+ (span_tri_v2_sign(v3, v1, v) == CONVEX))
+ {
+ return false;
+ }
+
+#ifdef USE_CONVEX_SKIP
+ coords_tot_concave_checked += 1;
+ if (coords_tot_concave_checked == pf->coords_tot_concave) {
+ break;
+ }
+#endif
+ }
+ }
+ return true;
+}
+
+static void pf_ear_tip_cut(PolyFill *pf, unsigned int index_ear_tip)
+{
+ unsigned int *tri = pf_tri_add(pf);
+
+ tri[0] = pf->indices[pf_index_prev(pf, index_ear_tip)];
+ tri[1] = pf->indices[index_ear_tip];
+ tri[2] = pf->indices[pf_index_next(pf, index_ear_tip)];
+
+ pf_coord_remove(pf, index_ear_tip);
+}
+
+static unsigned int pf_index_prev(const PolyFill *pf, const unsigned int index)
+{
+ return (index ? index : pf->coords_tot) - 1;
+}
+
+static unsigned int pf_index_next(const PolyFill *pf, unsigned index)
+{
+ return (index + 1) % pf->coords_tot;
+}
+
+/**
+* Triangulates the given (convex or concave) simple polygon to a list of triangle vertices.
+* \param vertices pairs describing vertices of the polygon, in either clockwise or counterclockwise order.
+* \return triples of triangle indices in clockwise order.
+* Note the returned array is reused for later calls to the same method.
+*/
+void BLI_polyfill_calc_ex(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*r_tris)[3],
+
+ unsigned int *r_indices, eSign *r_coords_sign)
+{
+ PolyFill pf;
+
+ /* localize */
+ unsigned int *indices = r_indices;
+ eSign *coords_sign = r_coords_sign;
+
+ unsigned int i;
+
+ /* assign all polyfill members here */
+ pf.indices = r_indices;
+ pf.coords = coords;
+ pf.coords_tot = coords_tot;
+ pf.coords_sign = r_coords_sign;
+#ifdef USE_CONVEX_SKIP
+ pf.coords_tot_concave = 0;
+#endif
+ pf.tris = r_tris;
+ pf.tris_tot = 0;
+
+ if ((coords_tot < 3) ||
+ cross_poly_v2((int)coords_tot, (float(*)[2])coords) > 0.0f)
+ {
+ for (i = 0; i < coords_tot; i++) {
+ indices[i] = i;
+ }
+ }
+ else {
+ /* reversed */
+ unsigned int n = coords_tot - 1;
+ for (i = 0; i < coords_tot; i++) {
+ indices[i] = (n - i);
+ }
+ }
+
+ for (i = 0; i < coords_tot; i++) {
+ coords_sign[i] = pf_coord_sign_calc(&pf, i);
+#ifdef USE_CONVEX_SKIP
+ if (coords_sign[i] != CONVEX) {
+ pf.coords_tot_concave += 1;
+ }
+#endif
+ }
+
+ pf_triangulate(&pf);
+}
+
+void BLI_polyfill_calc_arena(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*r_tris)[3],
+
+ struct MemArena *arena)
+{
+ unsigned int *indicies = BLI_memarena_alloc(arena, sizeof(*indicies) * coords_tot);
+ eSign *coords_sign = BLI_memarena_alloc(arena, sizeof(*coords_sign) * coords_tot);
+
+ BLI_polyfill_calc_ex(
+ coords, coords_tot,
+ r_tris,
+ /* cache */
+
+ indicies, coords_sign);
+
+ /* indicies & coords_sign are no longer needed,
+ * caller can clear arena */
+}
+
+void BLI_polyfill_calc(
+ const float (*coords)[2],
+ const unsigned int coords_tot,
+ unsigned int (*r_tris)[3])
+{
+ unsigned int *indicies = BLI_array_alloca(indicies, coords_tot);
+ eSign *coords_sign = BLI_array_alloca(coords_sign, coords_tot);
+
+ BLI_polyfill_calc_ex(
+ coords, coords_tot,
+ r_tris,
+ /* cache */
+
+ indicies, coords_sign);
+}
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index d36cd3cb394..c59a0195cb6 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -58,6 +58,20 @@ bool BLI_rctf_is_empty(const rctf *rect)
return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
}
+bool BLI_rcti_isect_x(const rcti *rect, const int x)
+{
+ if (x < rect->xmin) return false;
+ if (x > rect->xmax) return false;
+ return true;
+}
+
+bool BLI_rcti_isect_y(const rcti *rect, const int y)
+{
+ if (y < rect->ymin) return false;
+ if (y > rect->ymax) return false;
+ return true;
+}
+
bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
{
if (x < rect->xmin) return false;
@@ -67,13 +81,6 @@ bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
return true;
}
-/**
- * Determine if a rect is empty. An empty
- * rect is one with a zero (or negative)
- * width or height.
- *
- * \return True if \a rect is empty.
- */
bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
{
if (xy[0] < rect->xmin) return false;
@@ -83,6 +90,20 @@ bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
return true;
}
+bool BLI_rctf_isect_x(const rctf *rect, const float x)
+{
+ if (x < rect->xmin) return false;
+ if (x > rect->xmax) return false;
+ return true;
+}
+
+bool BLI_rctf_isect_y(const rctf *rect, const float y)
+{
+ if (y < rect->ymin) return false;
+ if (y > rect->ymax) return false;
+ return true;
+}
+
bool BLI_rctf_isect_pt(const rctf *rect, const float x, const float y)
{
if (x < rect->xmin) return false;
@@ -413,22 +434,22 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f
bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
{
- bool change = false;
- if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; }
- if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; }
- if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; }
- if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; }
- return change;
+ bool changed = false;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; changed = true; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; changed = true; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; changed = true; }
+ return changed;
}
bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
{
- bool change = false;
- if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; }
- if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; }
- if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; }
- if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; }
- return change;
+ bool changed = false;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; changed = true; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; changed = true; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; changed = true; }
+ return changed;
}
bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit)
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 24b8df78258..ba87a437032 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -46,6 +46,7 @@ set(SRC
intern/runtime.c
intern/undofile.c
intern/versioning_250.c
+ intern/versioning_260.c
intern/versioning_defaults.c
intern/versioning_legacy.c
intern/writefile.c
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6c6ca96480b..be76a8b8c88 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -40,6 +40,7 @@
#include <string.h> // for strrchr strncmp strstr
#include <math.h> // for fabs
#include <stdarg.h> /* for va_start/end */
+#include <time.h> /* for gmtime */
#include "BLI_utildefines.h"
#ifndef WIN32
@@ -251,8 +252,7 @@ static void convert_tface_mt(FileData *fd, Main *main);
* we could alternatively have a versions of a report function which forces printing - campbell
*/
-static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
-static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
+void blo_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
@@ -3025,7 +3025,7 @@ static void direct_link_lamp(FileData *fd, Lamp *la)
/* ************ READ keys ***************** */
-static void do_versions_key_uidgen(Key *key)
+void blo_do_versions_key_uidgen(Key *key)
{
KeyBlock *block;
@@ -3042,7 +3042,7 @@ static void lib_link_key(FileData *fd, Main *main)
for (key = main->key.first; key; key = key->id.next) {
/*check if we need to generate unique ids for the shapekeys*/
if (!key->uidgen) {
- do_versions_key_uidgen(key);
+ blo_do_versions_key_uidgen(key);
}
if (key->id.flag & LIB_NEED_LINK) {
@@ -3414,7 +3414,6 @@ static void direct_link_curve(FileData *fd, Curve *cu)
if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
}
- cu->disp.first = cu->disp.last = NULL;
cu->editnurb = NULL;
cu->lastsel = NULL;
cu->editfont = NULL;
@@ -4826,12 +4825,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
}
else if (md->type == eModifierType_LaplacianDeform) {
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
-
+
lmd->vertexco = newdataadr(fd, lmd->vertexco);
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
- BLI_endian_switch_float_array(lmd->vertexco, lmd->total_verts*3);
+ BLI_endian_switch_float_array(lmd->vertexco, lmd->total_verts * 3);
}
- lmd->cacheSystem = NULL;
+ lmd->cache_system = NULL;
}
}
}
@@ -5129,7 +5128,7 @@ static void lib_link_scene(FileData *fd, Main *main)
base->object = newlibadr_us(fd, sce->id.lib, base->object);
if (base->object == NULL) {
- BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: object lost from scene: '%s'"),
+ blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: object lost from scene: '%s'"),
sce->id.name + 2);
BLI_remlink(&sce->base, base);
if (base == sce->basact) sce->basact = NULL;
@@ -5531,6 +5530,10 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->drawmethod = -1;
win->drawfail = 0;
win->active = 0;
+
+ win->cursor = 0;
+ win->lastcursor = 0;
+ win->modalcursor = 0;
}
wm->timers.first = wm->timers.last = NULL;
@@ -5943,7 +5946,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
/* not very nice, but could help */
if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay;
-
+
/* free render engines for now */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
RegionView3D *rv3d= ar->regiondata;
@@ -6522,7 +6525,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
if (newmain->curlib) {
if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) {
- BKE_reportf_wrap(fd->reports, RPT_WARNING,
+ blo_reportf_wrap(fd->reports, RPT_WARNING,
TIP_("Library '%s', '%s' had multiple instances, save and reload!"),
lib->name, lib->filepath);
@@ -6777,6 +6780,15 @@ static void lib_link_movieTracks(FileData *fd, MovieClip *clip, ListBase *tracks
}
}
+static void lib_link_moviePlaneTracks(FileData *fd, MovieClip *clip, ListBase *tracksbase)
+{
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = tracksbase->first; plane_track; plane_track = plane_track->next) {
+ plane_track->image = newlibadr_us(fd, clip->id.lib, plane_track->image);
+ }
+}
+
static void lib_link_movieclip(FileData *fd, Main *main)
{
MovieClip *clip;
@@ -6792,6 +6804,7 @@ static void lib_link_movieclip(FileData *fd, Main *main)
clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd);
lib_link_movieTracks(fd, clip, &tracking->tracks);
+ lib_link_moviePlaneTracks(fd, clip, &tracking->plane_tracks);
for (object = tracking->objects.first; object; object = object->next) {
lib_link_movieTracks(fd, clip, &object->tracks);
@@ -7369,555 +7382,9 @@ static void convert_tface_mt(FileData *fd, Main *main)
}
}
-static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
- /* default Image output value should have 0 alpha */
- sock = node->outputs.first;
- ((bNodeSocketValueRGBA *)(sock->default_value))->value[3] = 0.0f;
- }
- }
-}
-
-static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
-{
- bNode *node;
- for (node=ntree->nodes.first; node; node=node->next) {
- if (node->type == CMP_NODE_ROTATE) {
- /* Convert degrees to radians. */
- bNodeSocket *sock = ((bNodeSocket*)node->inputs.first)->next;
- ((bNodeSocketValueFloat*)sock->default_value)->value = DEG2RADF(((bNodeSocketValueFloat*)sock->default_value)->value);
- }
- else if (node->type == CMP_NODE_DBLUR) {
- /* Convert degrees to radians. */
- NodeDBlurData *ndbd= node->storage;
- ndbd->angle = DEG2RADF(ndbd->angle);
- ndbd->spin = DEG2RADF(ndbd->spin);
- }
- else if (node->type == CMP_NODE_DEFOCUS) {
- /* Convert degrees to radians. */
- NodeDefocus *nqd = node->storage;
- /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
- nqd->rotation = DEG2RADF(nqd->rotation * 255.0f);
- }
- else if (node->type == CMP_NODE_CHROMA_MATTE) {
- /* Convert degrees to radians. */
- NodeChroma *ndc = node->storage;
- ndc->t1 = DEG2RADF(ndc->t1);
- ndc->t2 = DEG2RADF(ndc->t2);
- }
- else if (node->type == CMP_NODE_GLARE) {
- /* Convert degrees to radians. */
- NodeGlare *ndg = node->storage;
- /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
- ndg->angle_ofs = DEG2RADF(ndg->angle_ofs * 255.0f);
- }
- /* XXX TexMapping struct is used by other nodes too (at least node_composite_mapValue),
- * but not the rot part...
- */
- else if (node->type == SH_NODE_MAPPING) {
- /* Convert degrees to radians. */
- TexMapping *tmap = node->storage;
- tmap->rot[0] = DEG2RADF(tmap->rot[0]);
- tmap->rot[1] = DEG2RADF(tmap->rot[1]);
- tmap->rot[2] = DEG2RADF(tmap->rot[2]);
- }
- }
-}
-
-static void do_versions_image_settings_2_60(Scene *sce)
-{
- /* note: rd->subimtype is moved into individual settings now and no longer
- * exists */
- RenderData *rd = &sce->r;
- ImageFormatData *imf = &sce->r.im_format;
-
- /* we know no data loss happens here, the old values were in char range */
- imf->imtype = (char)rd->imtype;
- imf->planes = (char)rd->planes;
- imf->compress = (char)rd->quality;
- imf->quality = (char)rd->quality;
-
- /* default, was stored in multiple places, may override later */
- imf->depth = R_IMF_CHAN_DEPTH_8;
-
- /* openexr */
- imf->exr_codec = rd->quality & 7; /* strange but true! 0-4 are valid values, OPENEXR_COMPRESS */
-
- switch (imf->imtype) {
- case R_IMF_IMTYPE_OPENEXR:
- imf->depth = (rd->subimtype & R_OPENEXR_HALF) ? R_IMF_CHAN_DEPTH_16 : R_IMF_CHAN_DEPTH_32;
- if (rd->subimtype & R_PREVIEW_JPG) {
- imf->flag |= R_IMF_FLAG_PREVIEW_JPG;
- }
- if (rd->subimtype & R_OPENEXR_ZBUF) {
- imf->flag |= R_IMF_FLAG_ZBUF;
- }
- break;
- case R_IMF_IMTYPE_TIFF:
- if (rd->subimtype & R_TIFF_16BIT) {
- imf->depth= R_IMF_CHAN_DEPTH_16;
- }
- break;
- case R_IMF_IMTYPE_JP2:
- if (rd->subimtype & R_JPEG2K_16BIT) {
- imf->depth= R_IMF_CHAN_DEPTH_16;
- }
- else if (rd->subimtype & R_JPEG2K_12BIT) {
- imf->depth= R_IMF_CHAN_DEPTH_12;
- }
-
- if (rd->subimtype & R_JPEG2K_YCC) {
- imf->jp2_flag |= R_IMF_JP2_FLAG_YCC;
- }
- if (rd->subimtype & R_JPEG2K_CINE_PRESET) {
- imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_PRESET;
- }
- if (rd->subimtype & R_JPEG2K_CINE_48FPS) {
- imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
- }
- break;
- case R_IMF_IMTYPE_CINEON:
- case R_IMF_IMTYPE_DPX:
- if (rd->subimtype & R_CINEON_LOG) {
- imf->cineon_flag |= R_IMF_CINEON_FLAG_LOG;
- }
- break;
- }
-
-}
-
-/* socket use flags were only temporary before */
-static void do_versions_nodetree_socket_use_flags_2_62(bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
- bNodeLink *link;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_IN_USE;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_IN_USE;
- }
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_IN_USE;
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_IN_USE;
-
- for (link = ntree->links.first; link; link = link->next) {
- link->fromsock->flag |= SOCK_IN_USE;
- link->tosock->flag |= SOCK_IN_USE;
- }
-}
-
-static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_OUTPUT_FILE) {
- /* previous CMP_NODE_OUTPUT_FILE nodes get converted to multi-file outputs */
- NodeImageFile *old_data = node->storage;
- NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
- bNodeSocket *old_image = BLI_findlink(&node->inputs, 0);
- bNodeSocket *old_z = BLI_findlink(&node->inputs, 1);
- bNodeSocket *sock;
- char filename[FILE_MAXFILE];
-
- /* ugly, need to remove the old inputs list to avoid bad pointer checks when adding new sockets.
- * sock->storage is expected to contain path info in ntreeCompositOutputFileAddSocket.
- */
- node->inputs.first = node->inputs.last = NULL;
-
- node->storage = nimf;
-
- /* looks like storage data can be messed up somehow, stupid check here */
- if (old_data) {
- char basepath[FILE_MAXDIR];
-
- /* split off filename from the old path, to be used as socket sub-path */
- BLI_split_dirfile(old_data->name, basepath, filename, sizeof(basepath), sizeof(filename));
-
- BLI_strncpy(nimf->base_path, basepath, sizeof(nimf->base_path));
- nimf->format = old_data->im_format;
- }
- else {
- BLI_strncpy(filename, old_image->name, sizeof(filename));
- }
-
- /* if z buffer is saved, change the image type to multilayer exr.
- * XXX this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
- * i'm just assuming here that IRIZ means IRIS with z buffer ...
- */
- if (old_data && ELEM(old_data->im_format.imtype, R_IMF_IMTYPE_IRIZ, R_IMF_IMTYPE_OPENEXR)) {
- char sockpath[FILE_MAX];
-
- nimf->format.imtype = R_IMF_IMTYPE_MULTILAYER;
-
- BLI_snprintf(sockpath, sizeof(sockpath), "%s_Image", filename);
- sock = ntreeCompositOutputFileAddSocket(ntree, node, sockpath, &nimf->format);
- /* XXX later do_versions copies path from socket name, need to set this explicitely */
- BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
- if (old_image->link) {
- old_image->link->tosock = sock;
- sock->link = old_image->link;
- }
-
- BLI_snprintf(sockpath, sizeof(sockpath), "%s_Z", filename);
- sock = ntreeCompositOutputFileAddSocket(ntree, node, sockpath, &nimf->format);
- /* XXX later do_versions copies path from socket name, need to set this explicitely */
- BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
- if (old_z->link) {
- old_z->link->tosock = sock;
- sock->link = old_z->link;
- }
- }
- else {
- sock = ntreeCompositOutputFileAddSocket(ntree, node, filename, &nimf->format);
- /* XXX later do_versions copies path from socket name, need to set this explicitely */
- BLI_strncpy(sock->name, filename, sizeof(sock->name));
- if (old_image->link) {
- old_image->link->tosock = sock;
- sock->link = old_image->link;
- }
- }
-
- nodeRemoveSocket(ntree, node, old_image);
- nodeRemoveSocket(ntree, node, old_z);
- if (old_data)
- MEM_freeN(old_data);
- }
- else if (node->type==CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED) {
- NodeImageMultiFile *nimf = node->storage;
- bNodeSocket *sock;
-
- /* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */
- node->type = CMP_NODE_OUTPUT_FILE;
-
- /* initialize the node-wide image format from render data, if available */
- if (sce)
- nimf->format = sce->r.im_format;
-
- /* transfer render format toggle to node format toggle */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- NodeImageMultiFileSocket *simf = sock->storage;
- simf->use_node_format = simf->use_render_format;
- }
-
- /* we do have preview now */
- node->flag |= NODE_PREVIEW;
- }
- }
-}
-
-/* blue and red are swapped pre 2.62.1, be sane (red == red) now! */
-static void do_versions_mesh_mloopcol_swap_2_62_1(Mesh *me)
-{
- CustomDataLayer *layer;
- MLoopCol *mloopcol;
- int a;
- int i;
-
- for (a = 0; a < me->ldata.totlayer; a++) {
- layer = &me->ldata.layers[a];
-
- if (layer->type == CD_MLOOPCOL) {
- mloopcol = (MLoopCol *)layer->data;
- for (i = 0; i < me->totloop; i++, mloopcol++) {
- SWAP(char, mloopcol->r, mloopcol->b);
- }
- }
- }
-}
-
-static void do_versions_nodetree_multi_file_output_path_2_63_1(bNodeTree *ntree)
-{
- bNode *node;
-
- for (node=ntree->nodes.first; node; node=node->next) {
- if (node->type == CMP_NODE_OUTPUT_FILE) {
- bNodeSocket *sock;
- for (sock = node->inputs.first; sock; sock = sock->next) {
- NodeImageMultiFileSocket *input = sock->storage;
- /* input file path is stored in dedicated struct now instead socket name */
- BLI_strncpy(input->path, sock->name, sizeof(input->path));
- }
- }
- }
-}
-
-static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree)
-{
- bNode *node;
-
- for (node=ntree->nodes.first; node; node=node->next) {
- if (node->type == CMP_NODE_OUTPUT_FILE) {
- bNodeSocket *sock;
- for (sock = node->inputs.first; sock; sock = sock->next) {
- NodeImageMultiFileSocket *input = sock->storage;
-
- /* multilayer names are stored as separate strings now,
- * used the path string before, so copy it over.
- */
- BLI_strncpy(input->layer, input->path, sizeof(input->layer));
-
- /* paths/layer names also have to be unique now, initial check */
- ntreeCompositOutputFileUniquePath(&node->inputs, sock, input->path, '_');
- ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, input->layer, '_');
- }
- }
- }
-}
-
-static void do_versions_nodetree_image_layer_2_64_5(bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_IMAGE) {
- bNodeSocket *sock;
- for (sock = node->outputs.first; sock; sock = sock->next) {
- NodeImageLayer *output = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
-
- /* take pass index both from current storage ptr (actually an int) */
- output->pass_index = GET_INT_FROM_POINTER(sock->storage);
-
- /* replace socket data pointer */
- sock->storage = output;
- }
- }
- }
-}
-
-static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree)
-{
- bNode *node;
-
- for (node=ntree->nodes.first; node; node=node->next) {
- if (node->type==NODE_FRAME) {
- /* initialize frame node storage data */
- if (node->storage == NULL) {
- NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage");
- node->storage = data;
-
- /* copy current flags */
- data->flag = node->custom1;
-
- data->label_size = 20;
- }
- }
-
- /* initialize custom node color */
- node->color[0] = node->color[1] = node->color[2] = 0.608f; /* default theme color */
- }
-}
-
-static void do_version_logic_264(ListBase *regionbase)
-{
- ARegion *ar;
-
- /* view settings for logic changed */
- for (ar = regionbase->first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- if (ar->v2d.keeptot == 0) {
- ar->v2d.maxzoom = 1.5f;
-
- ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT;
- ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
- ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X;
- ar->v2d.keepofs = V2D_KEEPOFS_Y;
- }
- }
- }
-
-
-}
-
-static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
-{
- int i;
-
- for (i = 0; i < track->markersnr; i++) {
- MovieTrackingMarker *marker = &track->markers[i];
-
- if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) &&
- is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3]))
- {
- marker->pattern_corners[0][0] = track->pat_min[0];
- marker->pattern_corners[0][1] = track->pat_min[1];
-
- marker->pattern_corners[1][0] = track->pat_max[0];
- marker->pattern_corners[1][1] = track->pat_min[1];
-
- marker->pattern_corners[2][0] = track->pat_max[0];
- marker->pattern_corners[2][1] = track->pat_max[1];
-
- marker->pattern_corners[3][0] = track->pat_min[0];
- marker->pattern_corners[3][1] = track->pat_max[1];
- }
-
- if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) {
- copy_v2_v2(marker->search_min, track->search_min);
- copy_v2_v2(marker->search_max, track->search_max);
- }
- }
-}
-
-
-static const char *node_get_static_idname(int type, int treetype)
-{
- /* use static type info header to map static int type to identifier string */
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- case ID: return #Category #StructName;
-
- /* XXX hack, group types share a single static integer identifier, but are registered as separate types */
- if (type == NODE_GROUP) {
- switch (treetype) {
- case NTREE_COMPOSIT: return "CompositorNodeGroup";
- case NTREE_SHADER: return "ShaderNodeGroup";
- case NTREE_TEXTURE: return "TextureNodeGroup";
- }
- }
- else {
- switch (type) {
- #include "NOD_static_types.h"
- }
- }
- return "";
-}
-
-static const char *node_socket_get_static_idname(bNodeSocket *sock)
-{
- switch (sock->type) {
- case SOCK_FLOAT:
- {
- bNodeSocketValueFloat *dval = sock->default_value;
- return nodeStaticSocketType(SOCK_FLOAT, dval->subtype);
- }
- case SOCK_INT:
- {
- bNodeSocketValueInt *dval = sock->default_value;
- return nodeStaticSocketType(SOCK_INT, dval->subtype);
- }
- case SOCK_BOOLEAN:
- {
- return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE);
- }
- case SOCK_VECTOR:
- {
- bNodeSocketValueVector *dval = sock->default_value;
- return nodeStaticSocketType(SOCK_VECTOR, dval->subtype);
- }
- case SOCK_RGBA:
- {
- return nodeStaticSocketType(SOCK_RGBA, PROP_NONE);
- }
- case SOCK_STRING:
- {
- bNodeSocketValueString *dval = sock->default_value;
- return nodeStaticSocketType(SOCK_STRING, dval->subtype);
- }
- case SOCK_SHADER:
- {
- return nodeStaticSocketType(SOCK_SHADER, PROP_NONE);
- }
- }
- return "";
-}
-
-static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group))
-{
- /* initialize node tree type idname */
- {
- bNode *node;
- bNodeSocket *sock;
-
- ntree->typeinfo = NULL;
-
- /* tree type idname */
- switch (ntree->type) {
- case NTREE_COMPOSIT:
- strcpy(ntree->idname, "CompositorNodeTree");
- break;
- case NTREE_SHADER:
- strcpy(ntree->idname, "ShaderNodeTree");
- break;
- case NTREE_TEXTURE:
- strcpy(ntree->idname, "TextureNodeTree");
- break;
- }
-
- /* node type idname */
- for (node=ntree->nodes.first; node; node=node->next) {
- BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname));
-
- /* existing old nodes have been initialized already */
- node->flag |= NODE_INIT;
-
- /* sockets idname */
- for (sock = node->inputs.first; sock; sock = sock->next)
- BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
- for (sock = node->outputs.first; sock; sock = sock->next)
- BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
- }
- /* tree sockets idname */
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
- }
-
- /* initialize socket in_out values */
- {
- bNode *node;
- bNodeSocket *sock;
-
- for (node=ntree->nodes.first; node; node=node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->in_out = SOCK_IN;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->in_out = SOCK_OUT;
- }
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- sock->in_out = SOCK_IN;
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- sock->in_out = SOCK_OUT;
- }
-
- /* initialize socket identifier strings */
- {
- bNode *node;
- bNodeSocket *sock;
-
- for (node=ntree->nodes.first; node; node=node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
- BLI_uniquename(&node->inputs, sock, "socket", '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
- BLI_uniquename(&node->outputs, sock, "socket", '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
- }
- }
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
- BLI_uniquename(&ntree->inputs, sock, "socket", '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
- }
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
- BLI_uniquename(&ntree->outputs, sock, "socket", '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
- }
- }
-}
-
/* initialize userdef with non-UI dependency stuff */
/* other initializers (such as theme color defaults) go to resources.c */
-static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
+static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
{
Main *bmain = bfd->main;
UserDef *user = bfd->user;
@@ -7933,6 +7400,16 @@ static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
copy_v4_v4_char(btheme->tseq.grid, btheme->tseq.back);
}
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "WalkNavigation", "walk_navigation")) {
+ user->walk_navigation.mouse_speed = 1.0f;
+ user->walk_navigation.walk_speed = 2.5f; /* m/s */
+ user->walk_navigation.walk_speed_factor = 5.0f;
+ user->walk_navigation.view_height = 1.6f; /* m */
+ user->walk_navigation.jump_height = 0.4f; /* m */
+ user->walk_navigation.teleport_time = 0.2f; /* s */
+ }
+
}
static void do_versions(FileData *fd, Library *lib, Main *main)
@@ -7957,1902 +7434,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
blo_do_versions_pre250(fd, lib, main);
blo_do_versions_250(fd, lib, main);
-
- if (main->versionfile < 260) {
- {
- /* set default alpha value of Image outputs in image and render layer nodes to 0 */
- Scene *sce;
- bNodeTree *ntree;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- /* there are files with invalid audio_channels value, the real cause
- * is unknown, but we fix it here anyway to avoid crashes */
- if (sce->r.ffcodecdata.audio_channels == 0)
- sce->r.ffcodecdata.audio_channels = 2;
-
- if (sce->nodetree)
- do_versions_nodetree_image_default_alpha_output(sce->nodetree);
- }
-
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- do_versions_nodetree_image_default_alpha_output(ntree);
- }
-
- {
- /* support old particle dupliobject rotation settings */
- ParticleSettings *part;
-
- for (part=main->particle.first; part; part=part->id.next) {
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- part->draw |= PART_DRAW_ROTATE_OB;
-
- if (part->rotmode == 0)
- part->rotmode = PART_ROT_VEL;
- }
- }
- }
- }
-
- if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 1)) {
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ob->collision_boundtype= ob->boundtype;
- }
-
- {
- Camera *cam;
- for (cam = main->camera.first; cam; cam = cam->id.next) {
- if (cam->sensor_x < 0.01f)
- cam->sensor_x = DEFAULT_SENSOR_WIDTH;
-
- if (cam->sensor_y < 0.01f)
- cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
- }
- }
- }
-
- if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_MAPPING) {
- TexMapping *tex_mapping;
-
- tex_mapping= node->storage;
- tex_mapping->projx= PROJ_X;
- tex_mapping->projy= PROJ_Y;
- tex_mapping->projz= PROJ_Z;
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
- {
- /* Convert node angles to radians! */
- Scene *sce;
- Material *mat;
- bNodeTree *ntree;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- if (sce->nodetree)
- do_versions_nodetree_convert_angle(sce->nodetree);
- }
-
- for (mat = main->mat.first; mat; mat = mat->id.next) {
- if (mat->nodetree)
- do_versions_nodetree_convert_angle(mat->nodetree);
- }
-
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- do_versions_nodetree_convert_angle(ntree);
- }
-
- {
- /* Tomato compatibility code. */
- bScreen *sc;
- MovieClip *clip;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d= (View3D *)sl;
- if (v3d->bundle_size == 0.0f) {
- v3d->bundle_size = 0.2f;
- v3d->flag2 |= V3D_SHOW_RECONSTRUCTION;
- }
-
- if (v3d->bundle_drawtype == 0)
- v3d->bundle_drawtype = OB_PLAINAXES;
- }
- else if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
- if (sclip->scopes.track_preview_height == 0)
- sclip->scopes.track_preview_height = 120;
- }
- }
- }
- }
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTrackingTrack *track;
-
- if (clip->aspx < 1.0f) {
- clip->aspx = 1.0f;
- clip->aspy = 1.0f;
- }
-
- clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
- IMB_TC_FREE_RUN |
- IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN;
-
- if (clip->proxy.build_size_flag == 0)
- clip->proxy.build_size_flag = IMB_PROXY_25;
-
- if (clip->proxy.quality == 0)
- clip->proxy.quality = 90;
-
- if (clip->tracking.camera.pixel_aspect < 0.01f)
- clip->tracking.camera.pixel_aspect = 1.0f;
-
- track = clip->tracking.tracks.first;
- while (track) {
- if (track->minimum_correlation == 0.0f)
- track->minimum_correlation = 0.75f;
-
- track = track->next;
- }
- }
- }
- }
-
- if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 6)) {
- Scene *sce;
- MovieClip *clip;
- bScreen *sc;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- do_versions_image_settings_2_60(sce);
- }
-
- for (clip= main->movieclip.first; clip; clip= clip->id.next) {
- MovieTrackingSettings *settings= &clip->tracking.settings;
-
- if (settings->default_pattern_size == 0.0f) {
- settings->default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
- settings->default_minimum_correlation = 0.75;
- settings->default_pattern_size = 11;
- settings->default_search_size = 51;
- }
- }
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->flag2 &= ~V3D_RENDER_SHADOW;
- }
- }
- }
- }
-
- {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- /* convert delta addition into delta scale */
- int i;
- for (i= 0; i < 3; i++) {
- if ( (ob->dsize[i] == 0.0f) || /* simple case, user never touched dsize */
- (ob->size[i] == 0.0f)) /* cant scale the dsize to give a non zero result, so fallback to 1.0f */
- {
- ob->dscale[i] = 1.0f;
- }
- else {
- ob->dscale[i] = (ob->size[i] + ob->dsize[i]) / ob->size[i];
- }
- }
- }
- }
- }
- /* sigh, this dscale vs dsize version patching was not done right, fix for fix,
- * this intentionally checks an exact subversion, also note this was never in a release,
- * at some point this could be removed. */
- else if (main->versionfile == 260 && main->subversionfile == 6) {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- if (is_zero_v3(ob->dscale)) {
- fill_vn_fl(ob->dscale, 3, 1.0f);
- }
- }
- }
-
- if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 8)) {
- Brush *brush;
-
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
- brush->alpha= 1.0f;
- }
- }
-
- if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 1)) {
- {
- /* update use flags for node sockets (was only temporary before) */
- Scene *sce;
- Material *mat;
- Tex *tex;
- Lamp *lamp;
- World *world;
- bNodeTree *ntree;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- if (sce->nodetree)
- do_versions_nodetree_socket_use_flags_2_62(sce->nodetree);
- }
-
- for (mat = main->mat.first; mat; mat = mat->id.next) {
- if (mat->nodetree)
- do_versions_nodetree_socket_use_flags_2_62(mat->nodetree);
- }
-
- for (tex = main->tex.first; tex; tex = tex->id.next) {
- if (tex->nodetree)
- do_versions_nodetree_socket_use_flags_2_62(tex->nodetree);
- }
-
- for (lamp = main->lamp.first; lamp; lamp = lamp->id.next) {
- if (lamp->nodetree)
- do_versions_nodetree_socket_use_flags_2_62(lamp->nodetree);
- }
-
- for (world = main->world.first; world; world = world->id.next) {
- if (world->nodetree)
- do_versions_nodetree_socket_use_flags_2_62(world->nodetree);
- }
-
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- do_versions_nodetree_socket_use_flags_2_62(ntree);
- }
- }
- {
- /* Initialize BGE exit key to esc key */
- Scene *scene;
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (!scene->gm.exitkey)
- scene->gm.exitkey = 218; // Blender key code for ESC
- }
- }
- {
- MovieClip *clip;
- Object *ob;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object = tracking->objects.first;
-
- clip->proxy.build_tc_flag |= IMB_TC_RECORD_RUN_NO_GAPS;
-
- if (!tracking->settings.object_distance)
- tracking->settings.object_distance = 1.0f;
-
- if (tracking->objects.first == NULL)
- BKE_tracking_object_add(tracking, "Camera");
-
- while (tracking_object) {
- if (!tracking_object->scale)
- tracking_object->scale = 1.0f;
-
- tracking_object = tracking_object->next;
- }
- }
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- bConstraint *con;
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
-
- if (data->invmat[3][3] == 0.0f)
- unit_m4(data->invmat);
- }
- }
- }
- }
- {
- /* Warn the user if he is using ["Text"] properties for Font objects */
- Object *ob;
- bProperty *prop;
-
- for (ob= main->object.first; ob; ob= ob->id.next) {
- if (ob->type == OB_FONT) {
- prop = BKE_bproperty_object_get(ob, "Text");
- if (prop) {
- BKE_reportf_wrap(fd->reports, RPT_WARNING,
- TIP_("Game property name conflict in object '%s': text objects reserve the "
- "['Text'] game property to change their content through logic bricks"),
- ob->id.name + 2);
- }
- }
- }
- }
- }
-
- if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 2)) {
- {
- /* convert Camera Actuator values to defines */
- Object *ob;
- bActuator *act;
- for (ob = main->object.first; ob; ob= ob->id.next) {
- for (act= ob->actuators.first; act; act= act->next) {
- if (act->type == ACT_CAMERA) {
- bCameraActuator *ba= act->data;
-
- if (ba->axis==(float) 'x') ba->axis=OB_POSX;
- else if (ba->axis==(float)'y') ba->axis=OB_POSY;
- /* don't do an if/else to avoid imediate subversion bump*/
-// ba->axis=((ba->axis == (float)'x') ? OB_POSX_X : OB_POSY);
- }
- }
- }
- }
-
- {
- /* convert deprecated sculpt_paint_unified_* fields to
- * UnifiedPaintSettings */
- Scene *scene;
- for (scene= main->scene.first; scene; scene= scene->id.next) {
- ToolSettings *ts= scene->toolsettings;
- UnifiedPaintSettings *ups= &ts->unified_paint_settings;
- ups->size= ts->sculpt_paint_unified_size;
- ups->unprojected_radius= ts->sculpt_paint_unified_unprojected_radius;
- ups->alpha= ts->sculpt_paint_unified_alpha;
- ups->flag= ts->sculpt_paint_settings;
- }
- }
- }
-
- if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 3)) {
- {
- /* convert extended ascii to utf-8 for text editor */
- Text *text;
- for (text= main->text.first; text; text= text->id.next)
- if (!(text->flags & TXT_ISEXT)) {
- TextLine *tl;
-
- for (tl= text->lines.first; tl; tl= tl->next) {
- int added= txt_extended_ascii_as_utf8(&tl->line);
- tl->len+= added;
-
- /* reset cursor position if line was changed */
- if (added && tl == text->curl)
- text->curc = 0;
- }
- }
- }
- {
- /* set new dynamic paint values */
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md= ob->modifiers.first; md; md= md->next) {
- if (md->type == eModifierType_DynamicPaint) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->canvas) {
- DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
- for (; surface; surface=surface->next) {
- surface->color_dry_threshold = 1.0f;
- surface->influence_scale = 1.0f;
- surface->radius_scale = 1.0f;
- surface->flags |= MOD_DPAINT_USE_DRYING;
- }
- }
- }
- }
- }
- }
- }
-
- if (main->versionfile < 262) {
- Object *ob;
- for (ob=main->object.first; ob; ob= ob->id.next) {
- ModifierData *md;
-
- for (md=ob->modifiers.first; md; md=md->next) {
- if (md->type==eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData*) md;
- if (clmd->sim_parms)
- clmd->sim_parms->vel_damping = 1.0f;
- }
- }
- }
- }
-
- if (main->versionfile < 263) {
- /* set fluidsim rate. the version patch for this in 2.62 was wrong, so
- * try to correct it, if rate is 0.0 that's likely not intentional */
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Fluidsim) {
- FluidsimModifierData *fmd = (FluidsimModifierData *)md;
- if (fmd->fss->animRate == 0.0f)
- fmd->fss->animRate = 1.0f;
- }
- }
- }
- }
-
- if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 1)) {
- /* update use flags for node sockets (was only temporary before) */
- Scene *sce;
- bNodeTree *ntree;
-
- for (sce=main->scene.first; sce; sce=sce->id.next) {
- if (sce->nodetree)
- do_versions_nodetree_multi_file_output_format_2_62_1(sce, sce->nodetree);
- }
-
- /* XXX can't associate with scene for group nodes, image format will stay uninitialized */
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_versions_nodetree_multi_file_output_format_2_62_1(NULL, ntree);
- }
-
- /* only swap for pre-release bmesh merge which had MLoopCol red/blue swap */
- if (main->versionfile == 262 && main->subversionfile == 1) {
- {
- Mesh *me;
- for (me = main->mesh.first; me; me = me->id.next) {
- do_versions_mesh_mloopcol_swap_2_62_1(me);
- }
- }
- }
-
- if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 2)) {
- /* Set new idname of keyingsets from their now "label-only" name. */
- Scene *scene;
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- KeyingSet *ks;
- for (ks = scene->keyingsets.first; ks; ks = ks->next) {
- if (!ks->idname[0])
- BLI_strncpy(ks->idname, ks->name, sizeof(ks->idname));
- }
- }
- }
-
- if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 3)) {
- Object *ob;
- ModifierData *md;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Lattice) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- lmd->strength = 1.0f;
- }
- }
- }
- }
-
- if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 4)) {
- /* Read Viscosity presets from older files */
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Fluidsim) {
- FluidsimModifierData *fmd = (FluidsimModifierData *)md;
- if (fmd->fss->viscosityMode == 3) {
- fmd->fss->viscosityValue = 5.0;
- fmd->fss->viscosityExponent = 5;
- }
- else if (fmd->fss->viscosityMode == 4) {
- fmd->fss->viscosityValue = 2.0;
- fmd->fss->viscosityExponent = 3;
- }
- }
- }
- }
- }
-
-
-
- if (main->versionfile < 263) {
- /* Default for old files is to save particle rotations to pointcache */
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->flag |= PART_ROTATIONS;
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 1)) {
- /* file output node paths are now stored in the file info struct instead socket name */
- Scene *sce;
- bNodeTree *ntree;
-
- for (sce = main->scene.first; sce; sce=sce->id.next)
- if (sce->nodetree)
- do_versions_nodetree_multi_file_output_path_2_63_1(sce->nodetree);
- for (ntree = main->nodetree.first; ntree; ntree=ntree->id.next)
- do_versions_nodetree_multi_file_output_path_2_63_1(ntree);
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 3)) {
- Scene *scene;
- Brush *brush;
-
- /* For weight paint, each brush now gets its own weight;
- * unified paint settings also have weight. Update unified
- * paint settings and brushes with a default weight value. */
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- ToolSettings *ts = scene->toolsettings;
- if (ts) {
- ts->unified_paint_settings.weight = ts->vgroup_weight;
- ts->unified_paint_settings.flag |= UNIFIED_PAINT_WEIGHT;
- }
- }
-
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- brush->weight = 0.5;
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 2)) {
- bScreen *sc;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
- ARegion *ar;
- int hide = FALSE;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_PREVIEW) {
- if (ar->alignment != RGN_ALIGN_NONE) {
- ar->flag |= RGN_FLAG_HIDDEN;
- ar->v2d.flag &= ~V2D_IS_INITIALISED;
- ar->alignment = RGN_ALIGN_NONE;
-
- hide = TRUE;
- }
- }
- }
-
- if (hide) {
- sclip->view = SC_VIEW_CLIP;
- }
- }
- }
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 4))
- {
- Lamp *la;
- Camera *cam;
- Curve *cu;
-
- for (la = main->lamp.first; la; la = la->id.next) {
- if (la->shadow_frustum_size == 0.0f)
- la->shadow_frustum_size= 10.0f;
- }
-
- for (cam = main->camera.first; cam; cam = cam->id.next) {
- if (cam->flag & CAM_PANORAMA) {
- cam->type = CAM_PANO;
- cam->flag &= ~CAM_PANORAMA;
- }
- }
-
- for (cu = main->curve.first; cu; cu = cu->id.next) {
- if (cu->bevfac2 == 0.0f) {
- cu->bevfac1 = 0.0f;
- cu->bevfac2 = 1.0f;
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 5))
- {
- {
- /* file output node paths are now stored in the file info struct instead socket name */
- Scene *sce;
- bNodeTree *ntree;
-
- for (sce = main->scene.first; sce; sce=sce->id.next) {
- if (sce->nodetree) {
- do_versions_nodetree_file_output_layers_2_64_5(sce->nodetree);
- do_versions_nodetree_image_layer_2_64_5(sce->nodetree);
- }
- }
- for (ntree = main->nodetree.first; ntree; ntree=ntree->id.next) {
- do_versions_nodetree_file_output_layers_2_64_5(ntree);
- do_versions_nodetree_image_layer_2_64_5(ntree);
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 6))
- {
- /* update use flags for node sockets (was only temporary before) */
- Scene *sce;
- Material *mat;
- Tex *tex;
- Lamp *lamp;
- World *world;
- bNodeTree *ntree;
-
- for (sce=main->scene.first; sce; sce=sce->id.next)
- if (sce->nodetree)
- do_versions_nodetree_frame_2_64_6(sce->nodetree);
-
- for (mat=main->mat.first; mat; mat=mat->id.next)
- if (mat->nodetree)
- do_versions_nodetree_frame_2_64_6(mat->nodetree);
-
- for (tex=main->tex.first; tex; tex=tex->id.next)
- if (tex->nodetree)
- do_versions_nodetree_frame_2_64_6(tex->nodetree);
-
- for (lamp=main->lamp.first; lamp; lamp=lamp->id.next)
- if (lamp->nodetree)
- do_versions_nodetree_frame_2_64_6(lamp->nodetree);
-
- for (world=main->world.first; world; world=world->id.next)
- if (world->nodetree)
- do_versions_nodetree_frame_2_64_6(world->nodetree);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_versions_nodetree_frame_2_64_6(ntree);
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 7))
- {
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- int maxres = max_iii(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
- smd->domain->scale = smd->domain->dx * maxres;
- smd->domain->dx = 1.0f / smd->domain->scale;
- }
- }
- }
- }
- }
-
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 8))
- {
- /* set new deactivation values for game settings */
- Scene *sce;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- /* Game Settings */
- sce->gm.lineardeactthreshold = 0.8f;
- sce->gm.angulardeactthreshold = 1.0f;
- sce->gm.deactivationtime = 2.0f;
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
- NodeTexImage *tex = node->storage;
-
- tex->iuser.frames= 1;
- tex->iuser.sfra= 1;
- tex->iuser.fie_ima= 2;
- tex->iuser.ok= 1;
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) {
- {
- Scene *scene;
- // composite redesign
- for (scene=main->scene.first; scene; scene=scene->id.next) {
- if (scene->nodetree) {
- if (scene->nodetree->chunksize == 0) {
- scene->nodetree->chunksize = 256;
- }
- }
- }
-
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DEFOCUS) {
- NodeDefocus *data = node->storage;
- if (data->maxblur == 0.0f) {
- data->maxblur = 16.0f;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- {
- bScreen *sc;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
-
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
-
- if (sclip->around == 0) {
- sclip->around = V3D_CENTROID;
- }
- }
- }
- }
- }
- }
-
- {
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- clip->start_frame = 1;
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 11)) {
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTrackingTrack *track;
-
- track = clip->tracking.tracks.first;
- while (track) {
- do_versions_affine_tracker_track(track);
-
- track = track->next;
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 12)) {
- Material *ma;
-
- for (ma = main->mat.first; ma; ma = ma->id.next)
- if (ma->strand_widthfade == 2.0f)
- ma->strand_widthfade = 0.0f;
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DILATEERODE) {
- if (node->storage == NULL) {
- NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
- data->falloff = PROP_SMOOTH;
- node->storage = data;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
- ParticleSettings *part;
-
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_KEYING) {
- NodeKeyingData *data = node->storage;
-
- if (data->despill_balance == 0.0f) {
- data->despill_balance = 0.5f;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
-
- /* keep compatibility for dupliobject particle size */
- for (part=main->particle.first; part; part=part->id.next)
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
- if ((part->draw & PART_DRAW_ROTATE_OB) == 0)
- part->draw |= PART_DRAW_NO_SCALE_OB;
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_MASK) {
- if (node->storage == NULL) {
- NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
- /* move settings into own struct */
- data->size_x = (int)node->custom3;
- data->size_y = (int)node->custom4;
- node->custom3 = 0.5f; /* default shutter */
- node->storage = data;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) {
- Scene *scene;
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (scene->ed) {
- Sequence *seq;
-
- SEQ_BEGIN (scene->ed, seq)
- {
- Strip *strip = seq->strip;
-
- if (strip && strip->color_balance) {
- SequenceModifierData *smd;
- ColorBalanceModifierData *cbmd;
-
- smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance);
- cbmd = (ColorBalanceModifierData *) smd;
-
- cbmd->color_balance = *strip->color_balance;
-
- /* multiplication with color balance used is handled differently,
- * so we need to move multiplication to modifier so files would be
- * compatible
- */
- cbmd->color_multiply = seq->mul;
- seq->mul = 1.0f;
-
- MEM_freeN(strip->color_balance);
- strip->color_balance = NULL;
- }
- }
- SEQ_END
- }
- }
- }
-
- /* color management pipeline changes compatibility code */
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 19)) {
- Scene *scene;
- Image *ima;
- int colormanagement_disabled = FALSE;
-
- /* make scenes which are not using color management have got None as display device,
- * so they wouldn't perform linear-to-sRGB conversion on display
- */
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) {
- ColorManagedDisplaySettings *display_settings = &scene->display_settings;
-
- if (display_settings->display_device[0] == 0) {
- BKE_scene_disable_color_management(scene);
-
- }
-
- colormanagement_disabled = TRUE;
- }
- }
-
- for (ima = main->image.first; ima; ima = ima->id.next) {
- if (ima->source == IMA_SRC_VIEWER) {
- ima->flag |= IMA_VIEW_AS_RENDER;
- }
- else if (colormanagement_disabled) {
- /* if colormanagement not used, set image's color space to raw, so no sRGB->linear conversion
- * would happen on display and render
- * there's no clear way to check whether color management is enabled or not in render engine
- * so set all images to raw if there's at least one scene with color management disabled
- * this would still behave incorrect in cases when color management was used for only some
- * of scenes, but such a setup is crazy anyway and think it's fair enough to break compatibility
- * in that cases
- */
-
- BLI_strncpy(ima->colorspace_settings.name, "Raw", sizeof(ima->colorspace_settings.name));
- }
- }
- }
-
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 20)) {
- Key *key;
- for (key = main->key.first; key; key = key->id.next) {
- do_versions_key_uidgen(key);
- }
- }
-
- /* remove texco */
- if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 21)) {
- Material *ma;
- for (ma = main->mat.first; ma; ma = ma->id.next) {
- int a;
- for (a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a]) {
- if (ma->mtex[a]->texco == TEXCO_STICKY_) {
- ma->mtex[a]->texco = TEXCO_UV;
- }
- }
- }
- }
-
- {
- Mesh *me;
- for (me = main->mesh.first; me; me = me->id.next) {
- CustomData_update_typemap(&me->vdata);
- CustomData_free_layers(&me->vdata, CD_MSTICKY, me->totvert);
- }
- }
- }
-
- /* correction for files saved in blender version when BKE_pose_copy_data
- * didn't copy animation visualization, which lead to deadlocks on motion
- * path calculation for proxied armatures, see [#32742]
- */
- if (main->versionfile < 264) {
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- if (ob->pose) {
- if (ob->pose->avs.path_step == 0) {
- animviz_settings_init(&ob->pose->avs);
- }
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->type == SH_NODE_TEX_COORD)
- node->flag |= NODE_OPTIONS;
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) {
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object;
-
- for (tracking_object = tracking->objects.first;
- tracking_object;
- tracking_object = tracking_object->next)
- {
- if (tracking_object->keyframe1 == 0 && tracking_object->keyframe2 == 0) {
- tracking_object->keyframe1 = tracking->settings.keyframe1;
- tracking_object->keyframe2 = tracking->settings.keyframe2;
- }
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 3)) {
- /* smoke branch */
- {
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- /* keep branch saves if possible */
- if (!smd->domain->flame_max_temp) {
- smd->domain->burning_rate = 0.75f;
- smd->domain->flame_smoke = 1.0f;
- smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
- smd->domain->adapt_threshold = 0.02f;
- smd->domain->adapt_margin = 4;
- smd->domain->flame_smoke_color[0] = 0.7f;
- smd->domain->flame_smoke_color[1] = 0.7f;
- smd->domain->flame_smoke_color[2] = 0.7f;
- }
- }
- else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- if (!smd->flow->texture_size) {
- smd->flow->fuel_amount = 1.0;
- smd->flow->surface_distance = 1.5;
- smd->flow->color[0] = 0.7f;
- smd->flow->color[1] = 0.7f;
- smd->flow->color[2] = 0.7f;
- smd->flow->texture_size = 1.0f;
- }
- }
- }
- }
- }
- }
-
- /* render border for viewport */
- {
- bScreen *sc;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- if (v3d->render_border.xmin == 0.0f && v3d->render_border.ymin == 0.0f &&
- v3d->render_border.xmax == 0.0f && v3d->render_border.ymax == 0.0f)
- {
- v3d->render_border.xmax = 1.0f;
- v3d->render_border.ymax = 1.0f;
- }
- }
- }
- }
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) {
- /* set a unwrapping margin and ABF by default */
- Scene *scene;
-
- for (scene=main->scene.first; scene; scene=scene->id.next) {
- if (scene->toolsettings->uvcalc_margin == 0.0f) {
- scene->toolsettings->uvcalc_margin = 0.001f;
- scene->toolsettings->unwrapper = 0;
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
- /* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
- * Simply remove bad internal_links lists to avoid NULL pointers.
- */
- FOREACH_NODETREE(main, ntree, id) {
- bNode *node;
- bNodeLink *link, *nextlink;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- for (link = node->internal_links.first; link; link = nextlink) {
- nextlink = link->next;
- if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
- BLI_remlink(&node->internal_links, link);
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
- bScreen *sc;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- if ( sa->spacetype == SPACE_LOGIC)
- do_version_logic_264(&sa->regionbase);
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_LOGIC)
- do_version_logic_264(&sl->regionbase);
- }
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
- /* convert tiles size from resolution and number of tiles */
- {
- Scene *scene;
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (scene->r.tilex == 0 || scene->r.tiley == 1) {
- if (scene->r.xparts && scene->r.yparts) {
- /* scene could be set for panoramic rendering, so clamp with the
- * lowest possible tile size value
- */
- scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8);
- scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8);
- }
- else {
- /* happens when mixing using current trunk and previous release */
- scene->r.tilex = scene->r.tiley = 64;
- }
- }
- }
- }
-
- /* collision masks */
- {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- if (ob->col_group == 0) {
- ob->col_group = 0x01;
- ob->col_mask = 0xff;
- }
- }
- }
- }
-
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTrackingTrack *track;
- MovieTrackingObject *object;
-
- for (track = clip->tracking.tracks.first; track; track = track->next) {
- do_versions_affine_tracker_track(track);
- }
-
- for (object = clip->tracking.objects.first; object; object = object->next) {
- for (track = object->tracks.first; track; track = track->next) {
- do_versions_affine_tracker_track(track);
- }
- }
- }
- }
-
- if (main->versionfile < 265) {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- if (ob->step_height == 0.0f) {
- ob->step_height = 0.15f;
- ob->jump_speed = 10.0f;
- ob->fall_speed = 55.0f;
- }
- }
- }
-
- if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 3)) {
- bScreen *sc;
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- switch (sl->spacetype) {
- case SPACE_VIEW3D:
- {
- View3D *v3d = (View3D *)sl;
- v3d->flag2 |= V3D_SHOW_GPENCIL;
- break;
- }
- case SPACE_SEQ:
- {
- SpaceSeq *sseq = (SpaceSeq *)sl;
- sseq->flag |= SEQ_SHOW_GPENCIL;
- break;
- }
- case SPACE_IMAGE:
- {
- SpaceImage *sima = (SpaceImage *)sl;
- sima->flag |= SI_SHOW_GPENCIL;
- break;
- }
- case SPACE_NODE:
- {
- SpaceNode *snode = (SpaceNode *)sl;
- snode->flag |= SNODE_SHOW_GPENCIL;
- break;
- }
- case SPACE_CLIP:
- {
- SpaceClip *sclip = (SpaceClip *)sl;
- sclip->flag |= SC_SHOW_GPENCIL;
- break;
- }
- }
- }
- }
- }
- }
-
- if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
- Scene *scene;
- Image *image;
- Tex *tex;
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- Sequence *seq;
- bool set_premul = false;
-
- SEQ_BEGIN (scene->ed, seq)
- {
- if (seq->flag & SEQ_MAKE_PREMUL) {
- seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
- }
- else {
- BKE_sequence_alpha_mode_from_extension(seq);
- }
- }
- SEQ_END
-
- if (scene->r.bake_samples == 0)
- scene->r.bake_samples = 256;
-
- if (scene->world) {
- World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
-
- if (world && is_zero_v3(&world->horr)) {
- if ((world->skytype & WO_SKYBLEND) == 0 || is_zero_v3(&world->zenr)) {
- set_premul = true;
- }
- }
- }
- else
- set_premul = true;
-
- if (set_premul) {
- printf("2.66 versioning fix: replacing black sky with premultiplied alpha for scene %s\n", scene->id.name + 2);
- scene->r.alphamode = R_ALPHAPREMUL;
- }
- }
-
- for (image = main->image.first; image; image = image->id.next) {
- if (image->flag & IMA_DO_PREMUL) {
- image->alpha_mode = IMA_ALPHA_STRAIGHT;
- }
- else {
- BKE_image_alpha_mode_from_extension(image);
- }
- }
-
- for (tex = main->tex.first; tex; tex = tex->id.next) {
- if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
- image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
-
- if (image && (image->flag & IMA_DO_PREMUL) == 0)
- image->flag |= IMA_IGNORE_ALPHA;
- }
- }
-
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_IMAGE) {
- Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
-
- if (image) {
- if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
- node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
- else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) {
- /* texture use alpha was removed for 2.66 but added back again for 2.66a,
- * for compatibility all textures assumed it to be enabled */
- Tex *tex;
-
- for (tex = main->tex.first; tex; tex = tex->id.next)
- if (tex->type == TEX_IMAGE)
- tex->imaflag |= TEX_USEALPHA;
- }
-
- if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
- Curve *cu;
-
- for (cu = main->curve.first; cu; cu = cu->id.next) {
- if (cu->flag & (CU_FRONT | CU_BACK)) {
- if ( cu->ext1 != 0.0f || cu->ext2 != 0.0f) {
- Nurb *nu;
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- int a;
-
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
-
- while (a--) {
- bezt->radius = 1.0f;
- bezt++;
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
-
- while (a--) {
- bp->radius = 1.0f;
- bp++;
- }
- }
- }
- }
- }
- }
- }
-
- if (MAIN_VERSION_OLDER(main, 265, 9)) {
- Mesh *me;
- for (me = main->mesh.first; me; me = me->id.next) {
- BKE_mesh_do_versions_cd_flag_init(me);
- }
- }
-
- if (MAIN_VERSION_OLDER(main, 265, 10)) {
- Brush *br;
- for (br = main->brush.first; br; br = br->id.next) {
- if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
- br->mtex.brush_map_mode = MTEX_MAP_MODE_TILED;
- }
- }
- }
-
- // add storage for compositor translate nodes when not existing
- if (MAIN_VERSION_OLDER(main, 265, 11)) {
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
- node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (MAIN_VERSION_OLDER(main, 266, 2)) {
- FOREACH_NODETREE(main, ntree, id) {
- do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id));
- } FOREACH_NODETREE_END
- }
-
- if (MAIN_VERSION_OLDER(main, 266, 2)) {
- bScreen *sc;
- for (sc= main->screen.first; sc; sc= sc->id.next) {
- ScrArea *sa;
- for (sa= sc->areabase.first; sa; sa= sa->next) {
- SpaceLink *sl;
- for (sl= sa->spacedata.first; sl; sl= sl->next) {
- if (sl->spacetype==SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
-
- /* reset pointers to force tree path update from context */
- snode->nodetree = NULL;
- snode->edittree = NULL;
- snode->id = NULL;
- snode->from = NULL;
-
- /* convert deprecated treetype setting to tree_idname */
- switch (snode->treetype) {
- case NTREE_COMPOSIT:
- strcpy(snode->tree_idname, "CompositorNodeTree");
- break;
- case NTREE_SHADER:
- strcpy(snode->tree_idname, "ShaderNodeTree");
- break;
- case NTREE_TEXTURE:
- strcpy(snode->tree_idname, "TextureNodeTree");
- break;
- }
- }
- }
- }
- }
- }
-
- /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */
- {
- FOREACH_NODETREE(main, ntree, id) {
- /* XXX This should be kept without version check for now!
- * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links
- * to tree interface sockets for forward compatibility. These links need to be removed again
- * on file load in new versions.
- * Once forward compatibility is not required any longer, make a subversion bump
- * and only execute this for older versions.
- */
- ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP;
-
- /* Only add interface nodes once.
- * In old Blender versions they will be removed automatically due to undefined type */
- if (MAIN_VERSION_OLDER(main, 266, 2))
- ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE;
- }
- FOREACH_NODETREE_END
- }
-
- if (MAIN_VERSION_OLDER(main, 266, 3)) {
- {
- /* Fix for a very old issue:
- * Node names were nominally made unique in r24478 (2.50.8), but the do_versions check
- * to update existing node names only applied to main->nodetree (i.e. group nodes).
- * Uniqueness is now required for proper preview mapping,
- * so do this now to ensure old files don't break.
- */
- bNode *node;
- FOREACH_NODETREE(main, ntree, id) {
- if (id == &ntree->id)
- continue; /* already fixed for node groups */
-
- for (node = ntree->nodes.first; node; node = node->next)
- nodeUniqueName(ntree, node);
- }
- FOREACH_NODETREE_END
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 266, 4)) {
- Brush *brush;
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- default_mtex(&brush->mask_mtex);
-
- if (brush->ob_mode & OB_MODE_TEXTURE_PAINT) {
- brush->spacing /= 2;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 266, 6)) {
- Brush *brush;
- #define BRUSH_TEXTURE_OVERLAY (1 << 21)
-
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- brush->overlay_flags = 0;
- if (brush->flag & BRUSH_TEXTURE_OVERLAY)
- brush->overlay_flags |= (BRUSH_OVERLAY_PRIMARY | BRUSH_OVERLAY_CURSOR);
- }
- #undef BRUSH_TEXTURE_OVERLAY
- }
-
- if (main->versionfile < 267) {
- //if (!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "stencil_pos")) {
- Brush *brush;
-
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- if (brush->stencil_dimension[0] == 0) {
- brush->stencil_dimension[0] = 256;
- brush->stencil_dimension[1] = 256;
- brush->stencil_pos[0] = 256;
- brush->stencil_pos[1] = 256;
- }
- if (brush->mask_stencil_dimension[0] == 0) {
- brush->mask_stencil_dimension[0] = 256;
- brush->mask_stencil_dimension[1] = 256;
- brush->mask_stencil_pos[0] = 256;
- brush->mask_stencil_pos[1] = 256;
- }
- }
-
- /* TIP: to initialize new variables added, use the new function
- * DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
- * example:
- * if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
- * user->image_gpubuffer_limit = 10;
- */
-
- }
-
- /* default values in Freestyle settings */
- if (main->versionfile < 267) {
- Scene *sce;
- SceneRenderLayer *srl;
- FreestyleLineStyle *linestyle;
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- if (sce->r.line_thickness_mode == 0) {
- sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE;
- sce->r.unit_line_thickness = 1.0f;
- }
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- if (srl->freestyleConfig.mode == 0)
- srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE;
- if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
- srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL) {
- srl->freestyleConfig.raycasting_algorithm = 0; /* deprecated */
- srl->freestyleConfig.flags |= FREESTYLE_CULLING;
- }
- }
-
- /* not freestyle */
- {
- MeshStatVis *statvis = &sce->toolsettings->statvis;
- if (statvis->thickness_samples == 0) {
- statvis->overhang_axis = OB_NEGZ;
- statvis->overhang_min = 0;
- statvis->overhang_max = DEG2RADF(45.0f);
-
- statvis->thickness_max = 0.1f;
- statvis->thickness_samples = 1;
-
- statvis->distort_min = DEG2RADF(5.0f);
- statvis->distort_max = DEG2RADF(45.0f);
-
- statvis->sharp_min = DEG2RADF(90.0f);
- statvis->sharp_max = DEG2RADF(180.0f);
- }
- }
-
- }
- for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
-#if 1
- /* disable the Misc panel for now */
- if (linestyle->panel == LS_PANEL_MISC) {
- linestyle->panel = LS_PANEL_STROKES;
- }
-#endif
- if (linestyle->thickness_position == 0) {
- linestyle->thickness_position = LS_THICKNESS_CENTER;
- linestyle->thickness_ratio = 0.5f;
- }
- if (linestyle->chaining == 0)
- linestyle->chaining = LS_CHAINING_PLAIN;
- if (linestyle->rounds == 0)
- linestyle->rounds = 3;
- }
- }
-
- if (main->versionfile < 267) {
- /* Initialize the active_viewer_key for compositing */
- bScreen *screen;
- Scene *scene;
- bNodeInstanceKey active_viewer_key = {0};
- /* simply pick the first node space and use that for the active viewer key */
- for (screen = main->screen.first; screen; screen = screen->id.next) {
- ScrArea *sa;
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl= sl->next) {
- if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path = snode->treepath.last;
- if (!path)
- continue;
-
- active_viewer_key = path->parent_key;
- break;
- }
- }
- if (active_viewer_key.value != 0)
- break;
- }
- if (active_viewer_key.value != 0)
- break;
- }
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- /* NB: scene->nodetree is a local ID block, has been direct_link'ed */
- if (scene->nodetree)
- scene->nodetree->active_viewer_key = active_viewer_key;
- }
- }
-
- if (MAIN_VERSION_OLDER(main, 267, 1)) {
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- if (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) {
- smd->domain->highres_sampling = SM_HRES_LINEAR;
- }
- else {
- smd->domain->highres_sampling = SM_HRES_NEAREST;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 268, 1)) {
- Brush *brush;
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- brush->spacing = MAX2(1, brush->spacing);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 268, 2)) {
- Brush *brush;
- #define BRUSH_FIXED (1 << 6)
- for (brush = main->brush.first; brush; brush = brush->id.next) {
- brush->flag &= ~BRUSH_FIXED;
-
- if (brush->cursor_overlay_alpha < 2)
- brush->cursor_overlay_alpha = 33;
- if (brush->texture_overlay_alpha < 2)
- brush->texture_overlay_alpha = 33;
- if (brush->mask_overlay_alpha <2)
- brush->mask_overlay_alpha = 33;
- }
- #undef BRUSH_FIXED
- }
-
-
- if (!MAIN_VERSION_ATLEAST(main, 268, 4)) {
- bScreen *sc;
- Object *ob;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- bConstraint *con;
- for (con = ob->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
- bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)con->data;
- if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) data->projAxis = OB_POSX;
- else if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) data->projAxis = OB_POSY;
- else data->projAxis = OB_POSZ;
- data->projAxisSpace = CONSTRAINT_SPACE_LOCAL;
- }
- }
- }
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
- if (!smd->flow->particle_size) {
- smd->flow->particle_size = 1.0f;
- }
- }
- }
- }
- }
-
- /*
- * FIX some files have a zoom level of 0, and was checked during the drawing of the node space
- *
- * We moved this check to the do versions to be sure the value makes any sense.
- */
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- if (snode->zoom < 0.02f) {
- snode->zoom = 1.0;
- }
- }
- }
- }
- }
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
- bSensor *sens;
- bTouchSensor *ts;
- bCollisionSensor *cs;
- Material *ma;
-
- for (sens = ob->sensors.first; sens; sens = sens->next) {
- if (sens->type == SENS_TOUCH) {
- ts = sens->data;
- cs = MEM_callocN(sizeof(bCollisionSensor), "touch -> collision sensor do_version");
-
- if (ts->ma) {
- ma = blo_do_versions_newlibadr(fd, ob->id.lib, ts->ma);
- BLI_strncpy(cs->materialName, ma->id.name+2, sizeof(cs->materialName));
- }
-
- cs->mode = SENS_COLLISION_MATERIAL;
-
- MEM_freeN(ts);
-
- sens->data = cs;
- sens->type = sens->otype = SENS_COLLISION;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 268, 5)) {
- bScreen *sc;
- ScrArea *sa;
-
- /* add missing (+) expander in node editor */
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- ARegion *ar, *arnew;
-
- if (sa->spacetype == SPACE_NODE) {
- ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
-
- if (ar)
- continue;
-
- /* add subdiv level; after header */
- ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
-
- /* is error! */
- if (ar == NULL)
- continue;
-
- arnew = MEM_callocN(sizeof(ARegion), "node tools");
-
- BLI_insertlinkafter(&sa->regionbase, ar, arnew);
- arnew->regiontype = RGN_TYPE_TOOLS;
- arnew->alignment = RGN_ALIGN_LEFT;
-
- arnew->flag = RGN_FLAG_HIDDEN;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 269, 1)) {
- /* Removal of Cycles SSS Compatible falloff */
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
- if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) {
- node->custom1 = SHD_SUBSURFACE_CUBIC;
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (!MAIN_VERSION_ATLEAST(main, 269, 2)) {
- /* Initialize CDL settings for Color Balance nodes */
- FOREACH_NODETREE(main, ntree, id) {
- if (ntree->type == NTREE_COMPOSIT) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_COLORBALANCE) {
- NodeColorBalance *n = node->storage;
- if (node->custom1 == 0) {
- /* LGG mode stays the same, just init CDL settings */
- ntreeCompositColorBalanceSyncFromLGG(ntree, node);
- }
- else if (node->custom1 == 1) {
- /* CDL previously used same variables as LGG, copy them over
- * and then sync LGG for comparable results in both modes.
- */
- copy_v3_v3(n->offset, n->lift);
- copy_v3_v3(n->power, n->gamma);
- copy_v3_v3(n->slope, n->gain);
- ntreeCompositColorBalanceSyncFromCDL(ntree, node);
- }
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- {
- bScreen *sc;
- ScrArea *sa;
- SpaceLink *sl;
- Scene *scene;
-
- /* Update files using invalid (outdated) outlinevis Outliner values. */
- for (sc = main->screen.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so = (SpaceOops *)sl;
-
- if (!ELEM11(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
- SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
- SO_USERDEF))
- {
- so->outlinevis = SO_ALL_SCENES;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingTrack", "float", "weight")) {
- MovieClip *clip;
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *tracking_object;
- for (tracking_object = tracking->objects.first;
- tracking_object;
- tracking_object = tracking_object->next)
- {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- MovieTrackingTrack *track;
- for (track = tracksbase->first;
- track;
- track = track->next)
- {
- track->weight = 1.0f;
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "TriangulateModifierData", "int", "quad_method")) {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Triangulate) {
- TriangulateModifierData *tmd = (TriangulateModifierData *)md;
- if ((tmd->flag & MOD_TRIANGULATE_BEAUTY)) {
- tmd->quad_method = MOD_TRIANGULATE_QUAD_BEAUTY;
- tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY;
- }
- else {
- tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
- tmd->ngon_method = MOD_TRIANGULATE_NGON_SCANFILL;
- }
- }
- }
- }
- }
-
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (scene->gm.matmode == GAME_MAT_TEXFACE) {
- scene->gm.matmode = GAME_MAT_MULTITEX;
- }
- }
-
- /* 'Increment' mode disabled for nodes, use true grid snapping instead */
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_INCREMENT)
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
- }
-
- /* Update for removed "sound-only" option in FFMPEG export settings. */
-#ifdef WITH_FFMPEG
- for (scene = main->scene.first; scene; scene = scene->id.next) {
- if (scene->r.ffcodecdata.type >= FFMPEG_INVALID) {
- scene->r.ffcodecdata.type = FFMPEG_AVI;
- }
- }
-#endif
- }
+ blo_do_versions_260(fd, lib, main);
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
@@ -10182,7 +7764,7 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
if (ptr->curlib == NULL) {
const char *idname= bhead_id_name(fd, bhead);
- BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: Data refers to main .blend file: '%s' from %s"),
+ blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: Data refers to main .blend file: '%s' from %s"),
idname, mainvar->curlib->filepath);
return;
}
@@ -11514,7 +9096,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
if (mainptr->curlib->packedfile) {
PackedFile *pf = mainptr->curlib->packedfile;
- BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library: '%s'"),
+ blo_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library: '%s'"),
mainptr->curlib->name);
fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
@@ -11523,7 +9105,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase));
}
else {
- BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"),
+ blo_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"),
mainptr->curlib->filepath, mainptr->curlib->name);
fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
}
@@ -11577,7 +9159,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
if (fd == NULL) {
- BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"),
+ blo_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"),
mainptr->curlib->filepath);
}
}
@@ -11595,7 +9177,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
append_id_part(fd, mainptr, id, &realid);
if (!realid) {
- BKE_reportf_wrap(fd->reports, RPT_WARNING,
+ blo_reportf_wrap(fd->reports, RPT_WARNING,
TIP_("LIB ERROR: %s: '%s' missing from '%s'"),
BKE_idcode_to_name(GS(id->name)),
id->name + 2, mainptr->curlib->filepath);
@@ -11627,7 +9209,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
idn = id->next;
if (id->flag & LIB_READ) {
BLI_remlink(lbarray[a], id);
- BKE_reportf_wrap(basefd->reports, RPT_WARNING,
+ blo_reportf_wrap(basefd->reports, RPT_WARNING,
TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s'"),
BKE_idcode_to_name(GS(id->name)), id->name + 2, mainptr->curlib->filepath);
change_idid_adr(mainlist, basefd, id, NULL);
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 6d5fc056d89..fe22499d16f 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -34,6 +34,7 @@
#define __READFILE_H__
#include "zlib.h"
+#include "DNA_windowmanager_types.h" /* for ReportType */
struct OldNewMap;
struct MemFile;
@@ -43,6 +44,7 @@ struct Object;
struct PartEff;
struct View3D;
struct bNodeTree;
+struct Key;
typedef struct FileData {
// linked list of BHeadN's
@@ -145,6 +147,8 @@ char *bhead_id_name(FileData *fd, BHead *bhead);
/* do versions stuff */
+void blo_reportf_wrap(struct ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
+
void blo_do_versions_oldnewmap_insert(struct OldNewMap *onm, void *oldaddr, void *newaddr, int nr);
void *blo_do_versions_newlibadr(struct FileData *fd, void *lib, void *adr);
void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
@@ -152,9 +156,11 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
void blo_do_version_old_trackto_to_constraints(struct Object *ob);
void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions);
+void blo_do_versions_key_uidgen(struct Key *key);
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
+void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *main);
#endif
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
new file mode 100644
index 00000000000..5acf6319d2f
--- /dev/null
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -0,0 +1,2648 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/blenloader/intern/versioning_260.c
+ * \ingroup blenloader
+ */
+
+#include "zlib.h"
+
+#include "BLI_utildefines.h"
+
+/* allow readfile to use deprecated functionality */
+#define DNA_DEPRECATED_ALLOW
+
+#include "DNA_anim_types.h"
+#include "DNA_actuator_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_genfile.h"
+#include "DNA_key_types.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_text_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sensor_types.h"
+#include "DNA_sdna_types.h"
+#include "DNA_smoke_types.h"
+#include "DNA_space_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BLF_translation.h"
+
+#include "BKE_anim.h"
+#include "BKE_image.h"
+#include "BKE_main.h" // for Main
+#include "BKE_mesh.h" // for ME_ defines (patching)
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_property.h" // for BKE_bproperty_object_get
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_sequencer.h"
+#include "BKE_text.h" // for txt_extended_ascii_as_utf8
+#include "BKE_texture.h"
+#include "BKE_tracking.h"
+#include "BKE_writeffmpeg.h"
+
+#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
+
+#include "NOD_texture.h"
+
+#include "BLO_readfile.h"
+
+#include "readfile.h"
+
+static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
+ /* default Image output value should have 0 alpha */
+ sock = node->outputs.first;
+ ((bNodeSocketValueRGBA *)(sock->default_value))->value[3] = 0.0f;
+ }
+ }
+}
+
+static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
+{
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_ROTATE) {
+ /* Convert degrees to radians. */
+ bNodeSocket *sock = ((bNodeSocket *)node->inputs.first)->next;
+ ((bNodeSocketValueFloat *)sock->default_value)->value =
+ DEG2RADF(((bNodeSocketValueFloat *)sock->default_value)->value);
+ }
+ else if (node->type == CMP_NODE_DBLUR) {
+ /* Convert degrees to radians. */
+ NodeDBlurData *ndbd = node->storage;
+ ndbd->angle = DEG2RADF(ndbd->angle);
+ ndbd->spin = DEG2RADF(ndbd->spin);
+ }
+ else if (node->type == CMP_NODE_DEFOCUS) {
+ /* Convert degrees to radians. */
+ NodeDefocus *nqd = node->storage;
+ /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
+ nqd->rotation = DEG2RADF(nqd->rotation * 255.0f);
+ }
+ else if (node->type == CMP_NODE_CHROMA_MATTE) {
+ /* Convert degrees to radians. */
+ NodeChroma *ndc = node->storage;
+ ndc->t1 = DEG2RADF(ndc->t1);
+ ndc->t2 = DEG2RADF(ndc->t2);
+ }
+ else if (node->type == CMP_NODE_GLARE) {
+ /* Convert degrees to radians. */
+ NodeGlare *ndg = node->storage;
+ /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
+ ndg->angle_ofs = DEG2RADF(ndg->angle_ofs * 255.0f);
+ }
+ /* XXX TexMapping struct is used by other nodes too (at least node_composite_mapValue),
+ * but not the rot part...
+ */
+ else if (node->type == SH_NODE_MAPPING) {
+ /* Convert degrees to radians. */
+ TexMapping *tmap = node->storage;
+ tmap->rot[0] = DEG2RADF(tmap->rot[0]);
+ tmap->rot[1] = DEG2RADF(tmap->rot[1]);
+ tmap->rot[2] = DEG2RADF(tmap->rot[2]);
+ }
+ }
+}
+
+static void do_versions_image_settings_2_60(Scene *sce)
+{
+ /* note: rd->subimtype is moved into individual settings now and no longer
+ * exists */
+ RenderData *rd = &sce->r;
+ ImageFormatData *imf = &sce->r.im_format;
+
+ /* we know no data loss happens here, the old values were in char range */
+ imf->imtype = (char)rd->imtype;
+ imf->planes = (char)rd->planes;
+ imf->compress = (char)rd->quality;
+ imf->quality = (char)rd->quality;
+
+ /* default, was stored in multiple places, may override later */
+ imf->depth = R_IMF_CHAN_DEPTH_8;
+
+ /* openexr */
+ imf->exr_codec = rd->quality & 7; /* strange but true! 0-4 are valid values, OPENEXR_COMPRESS */
+
+ switch (imf->imtype) {
+ case R_IMF_IMTYPE_OPENEXR:
+ imf->depth = (rd->subimtype & R_OPENEXR_HALF) ? R_IMF_CHAN_DEPTH_16 : R_IMF_CHAN_DEPTH_32;
+ if (rd->subimtype & R_PREVIEW_JPG) {
+ imf->flag |= R_IMF_FLAG_PREVIEW_JPG;
+ }
+ if (rd->subimtype & R_OPENEXR_ZBUF) {
+ imf->flag |= R_IMF_FLAG_ZBUF;
+ }
+ break;
+ case R_IMF_IMTYPE_TIFF:
+ if (rd->subimtype & R_TIFF_16BIT) {
+ imf->depth = R_IMF_CHAN_DEPTH_16;
+ }
+ break;
+ case R_IMF_IMTYPE_JP2:
+ if (rd->subimtype & R_JPEG2K_16BIT) {
+ imf->depth = R_IMF_CHAN_DEPTH_16;
+ }
+ else if (rd->subimtype & R_JPEG2K_12BIT) {
+ imf->depth = R_IMF_CHAN_DEPTH_12;
+ }
+
+ if (rd->subimtype & R_JPEG2K_YCC) {
+ imf->jp2_flag |= R_IMF_JP2_FLAG_YCC;
+ }
+ if (rd->subimtype & R_JPEG2K_CINE_PRESET) {
+ imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_PRESET;
+ }
+ if (rd->subimtype & R_JPEG2K_CINE_48FPS) {
+ imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
+ }
+ break;
+ case R_IMF_IMTYPE_CINEON:
+ case R_IMF_IMTYPE_DPX:
+ if (rd->subimtype & R_CINEON_LOG) {
+ imf->cineon_flag |= R_IMF_CINEON_FLAG_LOG;
+ }
+ break;
+ }
+}
+
+/* socket use flags were only temporary before */
+static void do_versions_nodetree_socket_use_flags_2_62(bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+ bNodeLink *link;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ sock->flag &= ~SOCK_IN_USE;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ sock->flag &= ~SOCK_IN_USE;
+ }
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ sock->flag &= ~SOCK_IN_USE;
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ sock->flag &= ~SOCK_IN_USE;
+
+ for (link = ntree->links.first; link; link = link->next) {
+ link->fromsock->flag |= SOCK_IN_USE;
+ link->tosock->flag |= SOCK_IN_USE;
+ }
+}
+
+static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_OUTPUT_FILE) {
+ /* previous CMP_NODE_OUTPUT_FILE nodes get converted to multi-file outputs */
+ NodeImageFile *old_data = node->storage;
+ NodeImageMultiFile *nimf = MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
+ bNodeSocket *old_image = BLI_findlink(&node->inputs, 0);
+ bNodeSocket *old_z = BLI_findlink(&node->inputs, 1);
+ bNodeSocket *sock;
+ char filename[FILE_MAXFILE];
+
+ /* ugly, need to remove the old inputs list to avoid bad pointer checks when adding new sockets.
+ * sock->storage is expected to contain path info in ntreeCompositOutputFileAddSocket.
+ */
+ node->inputs.first = node->inputs.last = NULL;
+
+ node->storage = nimf;
+
+ /* looks like storage data can be messed up somehow, stupid check here */
+ if (old_data) {
+ char basepath[FILE_MAXDIR];
+
+ /* split off filename from the old path, to be used as socket sub-path */
+ BLI_split_dirfile(old_data->name, basepath, filename, sizeof(basepath), sizeof(filename));
+
+ BLI_strncpy(nimf->base_path, basepath, sizeof(nimf->base_path));
+ nimf->format = old_data->im_format;
+ }
+ else {
+ BLI_strncpy(filename, old_image->name, sizeof(filename));
+ }
+
+ /* if z buffer is saved, change the image type to multilayer exr.
+ * XXX this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
+ * i'm just assuming here that IRIZ means IRIS with z buffer ...
+ */
+ if (old_data && ELEM(old_data->im_format.imtype, R_IMF_IMTYPE_IRIZ, R_IMF_IMTYPE_OPENEXR)) {
+ char sockpath[FILE_MAX];
+
+ nimf->format.imtype = R_IMF_IMTYPE_MULTILAYER;
+
+ BLI_snprintf(sockpath, sizeof(sockpath), "%s_Image", filename);
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, sockpath, &nimf->format);
+ /* XXX later do_versions copies path from socket name, need to set this explicitely */
+ BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
+ if (old_image->link) {
+ old_image->link->tosock = sock;
+ sock->link = old_image->link;
+ }
+
+ BLI_snprintf(sockpath, sizeof(sockpath), "%s_Z", filename);
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, sockpath, &nimf->format);
+ /* XXX later do_versions copies path from socket name, need to set this explicitely */
+ BLI_strncpy(sock->name, sockpath, sizeof(sock->name));
+ if (old_z->link) {
+ old_z->link->tosock = sock;
+ sock->link = old_z->link;
+ }
+ }
+ else {
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, filename, &nimf->format);
+ /* XXX later do_versions copies path from socket name, need to set this explicitely */
+ BLI_strncpy(sock->name, filename, sizeof(sock->name));
+ if (old_image->link) {
+ old_image->link->tosock = sock;
+ sock->link = old_image->link;
+ }
+ }
+
+ nodeRemoveSocket(ntree, node, old_image);
+ nodeRemoveSocket(ntree, node, old_z);
+ if (old_data)
+ MEM_freeN(old_data);
+ }
+ else if (node->type == CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED) {
+ NodeImageMultiFile *nimf = node->storage;
+ bNodeSocket *sock;
+
+ /* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */
+ node->type = CMP_NODE_OUTPUT_FILE;
+
+ /* initialize the node-wide image format from render data, if available */
+ if (sce)
+ nimf->format = sce->r.im_format;
+
+ /* transfer render format toggle to node format toggle */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ NodeImageMultiFileSocket *simf = sock->storage;
+ simf->use_node_format = simf->use_render_format;
+ }
+
+ /* we do have preview now */
+ node->flag |= NODE_PREVIEW;
+ }
+ }
+}
+
+/* blue and red are swapped pre 2.62.1, be sane (red == red) now! */
+static void do_versions_mesh_mloopcol_swap_2_62_1(Mesh *me)
+{
+ CustomDataLayer *layer;
+ MLoopCol *mloopcol;
+ int a;
+ int i;
+
+ for (a = 0; a < me->ldata.totlayer; a++) {
+ layer = &me->ldata.layers[a];
+
+ if (layer->type == CD_MLOOPCOL) {
+ mloopcol = (MLoopCol *)layer->data;
+ for (i = 0; i < me->totloop; i++, mloopcol++) {
+ SWAP(char, mloopcol->r, mloopcol->b);
+ }
+ }
+ }
+}
+
+static void do_versions_nodetree_multi_file_output_path_2_63_1(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_OUTPUT_FILE) {
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ NodeImageMultiFileSocket *input = sock->storage;
+ /* input file path is stored in dedicated struct now instead socket name */
+ BLI_strncpy(input->path, sock->name, sizeof(input->path));
+ }
+ }
+ }
+}
+
+static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_OUTPUT_FILE) {
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ NodeImageMultiFileSocket *input = sock->storage;
+
+ /* multilayer names are stored as separate strings now,
+ * used the path string before, so copy it over.
+ */
+ BLI_strncpy(input->layer, input->path, sizeof(input->layer));
+
+ /* paths/layer names also have to be unique now, initial check */
+ ntreeCompositOutputFileUniquePath(&node->inputs, sock, input->path, '_');
+ ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, input->layer, '_');
+ }
+ }
+ }
+}
+
+static void do_versions_nodetree_image_layer_2_64_5(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_IMAGE) {
+ bNodeSocket *sock;
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ NodeImageLayer *output = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+
+ /* take pass index both from current storage ptr (actually an int) */
+ output->pass_index = GET_INT_FROM_POINTER(sock->storage);
+
+ /* replace socket data pointer */
+ sock->storage = output;
+ }
+ }
+ }
+}
+
+static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_FRAME) {
+ /* initialize frame node storage data */
+ if (node->storage == NULL) {
+ NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage");
+ node->storage = data;
+
+ /* copy current flags */
+ data->flag = node->custom1;
+
+ data->label_size = 20;
+ }
+ }
+
+ /* initialize custom node color */
+ node->color[0] = node->color[1] = node->color[2] = 0.608f; /* default theme color */
+ }
+}
+
+static void do_version_logic_264(ListBase *regionbase)
+{
+ ARegion *ar;
+
+ /* view settings for logic changed */
+ for (ar = regionbase->first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (ar->v2d.keeptot == 0) {
+ ar->v2d.maxzoom = 1.5f;
+
+ ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT;
+ ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
+ ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X;
+ ar->v2d.keepofs = V2D_KEEPOFS_Y;
+ }
+ }
+ }
+}
+
+static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
+{
+ int i;
+
+ for (i = 0; i < track->markersnr; i++) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) &&
+ is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3]))
+ {
+ marker->pattern_corners[0][0] = track->pat_min[0];
+ marker->pattern_corners[0][1] = track->pat_min[1];
+
+ marker->pattern_corners[1][0] = track->pat_max[0];
+ marker->pattern_corners[1][1] = track->pat_min[1];
+
+ marker->pattern_corners[2][0] = track->pat_max[0];
+ marker->pattern_corners[2][1] = track->pat_max[1];
+
+ marker->pattern_corners[3][0] = track->pat_min[0];
+ marker->pattern_corners[3][1] = track->pat_max[1];
+ }
+
+ if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) {
+ copy_v2_v2(marker->search_min, track->search_min);
+ copy_v2_v2(marker->search_max, track->search_max);
+ }
+ }
+}
+
+static const char *node_get_static_idname(int type, int treetype)
+{
+ /* use static type info header to map static int type to identifier string */
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ case ID: return #Category #StructName;
+
+ /* XXX hack, group types share a single static integer identifier, but are registered as separate types */
+ if (type == NODE_GROUP) {
+ switch (treetype) {
+ case NTREE_COMPOSIT: return "CompositorNodeGroup";
+ case NTREE_SHADER: return "ShaderNodeGroup";
+ case NTREE_TEXTURE: return "TextureNodeGroup";
+ }
+ }
+ else {
+ switch (type) {
+ #include "NOD_static_types.h"
+ }
+ }
+ return "";
+}
+
+static const char *node_socket_get_static_idname(bNodeSocket *sock)
+{
+ switch (sock->type) {
+ case SOCK_FLOAT:
+ {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_FLOAT, dval->subtype);
+ }
+ case SOCK_INT:
+ {
+ bNodeSocketValueInt *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_INT, dval->subtype);
+ }
+ case SOCK_BOOLEAN:
+ {
+ return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE);
+ }
+ case SOCK_VECTOR:
+ {
+ bNodeSocketValueVector *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_VECTOR, dval->subtype);
+ }
+ case SOCK_RGBA:
+ {
+ return nodeStaticSocketType(SOCK_RGBA, PROP_NONE);
+ }
+ case SOCK_STRING:
+ {
+ bNodeSocketValueString *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_STRING, dval->subtype);
+ }
+ case SOCK_SHADER:
+ {
+ return nodeStaticSocketType(SOCK_SHADER, PROP_NONE);
+ }
+ }
+ return "";
+}
+
+static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group))
+{
+ /* initialize node tree type idname */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->typeinfo = NULL;
+
+ /* tree type idname */
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ strcpy(ntree->idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(ntree->idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(ntree->idname, "TextureNodeTree");
+ break;
+ }
+
+ /* node type idname */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname));
+
+ /* existing old nodes have been initialized already */
+ node->flag |= NODE_INIT;
+
+ /* sockets idname */
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+ /* tree sockets idname */
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+
+ /* initialize socket in_out values */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+
+ /* initialize socket identifier strings */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->inputs, sock, "socket", '.',
+ offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->outputs, sock, "socket", '.',
+ offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->inputs, sock, "socket", '.',
+ offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->outputs, sock, "socket", '.',
+ offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+}
+
+void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
+{
+ if (main->versionfile < 260) {
+ {
+ /* set default alpha value of Image outputs in image and render layer nodes to 0 */
+ Scene *sce;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ /* there are files with invalid audio_channels value, the real cause
+ * is unknown, but we fix it here anyway to avoid crashes */
+ if (sce->r.ffcodecdata.audio_channels == 0)
+ sce->r.ffcodecdata.audio_channels = 2;
+
+ if (sce->nodetree)
+ do_versions_nodetree_image_default_alpha_output(sce->nodetree);
+ }
+
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ do_versions_nodetree_image_default_alpha_output(ntree);
+ }
+
+ {
+ /* support old particle dupliobject rotation settings */
+ ParticleSettings *part;
+
+ for (part = main->particle.first; part; part = part->id.next) {
+ if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+ part->draw |= PART_DRAW_ROTATE_OB;
+
+ if (part->rotmode == 0)
+ part->rotmode = PART_ROT_VEL;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 1)) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ob->collision_boundtype = ob->boundtype;
+ }
+
+ {
+ Camera *cam;
+ for (cam = main->camera.first; cam; cam = cam->id.next) {
+ if (cam->sensor_x < 0.01f)
+ cam->sensor_x = DEFAULT_SENSOR_WIDTH;
+
+ if (cam->sensor_y < 0.01f)
+ cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
+ }
+ }
+ }
+
+ if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_MAPPING) {
+ TexMapping *tex_mapping;
+
+ tex_mapping = node->storage;
+ tex_mapping->projx = PROJ_X;
+ tex_mapping->projy = PROJ_Y;
+ tex_mapping->projz = PROJ_Z;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
+ {
+ /* Convert node angles to radians! */
+ Scene *sce;
+ Material *mat;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree)
+ do_versions_nodetree_convert_angle(sce->nodetree);
+ }
+
+ for (mat = main->mat.first; mat; mat = mat->id.next) {
+ if (mat->nodetree)
+ do_versions_nodetree_convert_angle(mat->nodetree);
+ }
+
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ do_versions_nodetree_convert_angle(ntree);
+ }
+
+ {
+ /* Tomato compatibility code. */
+ bScreen *sc;
+ MovieClip *clip;
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->bundle_size == 0.0f) {
+ v3d->bundle_size = 0.2f;
+ v3d->flag2 |= V3D_SHOW_RECONSTRUCTION;
+ }
+
+ if (v3d->bundle_drawtype == 0)
+ v3d->bundle_drawtype = OB_PLAINAXES;
+ }
+ else if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = (SpaceClip *)sl;
+ if (sclip->scopes.track_preview_height == 0)
+ sclip->scopes.track_preview_height = 120;
+ }
+ }
+ }
+ }
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTrackingTrack *track;
+
+ if (clip->aspx < 1.0f) {
+ clip->aspx = 1.0f;
+ clip->aspy = 1.0f;
+ }
+
+ clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
+ IMB_TC_FREE_RUN |
+ IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN;
+
+ if (clip->proxy.build_size_flag == 0)
+ clip->proxy.build_size_flag = IMB_PROXY_25;
+
+ if (clip->proxy.quality == 0)
+ clip->proxy.quality = 90;
+
+ if (clip->tracking.camera.pixel_aspect < 0.01f)
+ clip->tracking.camera.pixel_aspect = 1.0f;
+
+ track = clip->tracking.tracks.first;
+ while (track) {
+ if (track->minimum_correlation == 0.0f)
+ track->minimum_correlation = 0.75f;
+
+ track = track->next;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 6)) {
+ Scene *sce;
+ MovieClip *clip;
+ bScreen *sc;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ do_versions_image_settings_2_60(sce);
+ }
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTrackingSettings *settings = &clip->tracking.settings;
+
+ if (settings->default_pattern_size == 0.0f) {
+ settings->default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
+ settings->default_minimum_correlation = 0.75;
+ settings->default_pattern_size = 11;
+ settings->default_search_size = 51;
+ }
+ }
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->flag2 &= ~V3D_RENDER_SHADOW;
+ }
+ }
+ }
+ }
+
+ {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ /* convert delta addition into delta scale */
+ int i;
+ for (i = 0; i < 3; i++) {
+ if ( (ob->dsize[i] == 0.0f) || /* simple case, user never touched dsize */
+ (ob->size[i] == 0.0f)) /* cant scale the dsize to give a non zero result,
+ so fallback to 1.0f */
+ {
+ ob->dscale[i] = 1.0f;
+ }
+ else {
+ ob->dscale[i] = (ob->size[i] + ob->dsize[i]) / ob->size[i];
+ }
+ }
+ }
+ }
+ }
+ /* sigh, this dscale vs dsize version patching was not done right, fix for fix,
+ * this intentionally checks an exact subversion, also note this was never in a release,
+ * at some point this could be removed. */
+ else if (main->versionfile == 260 && main->subversionfile == 6) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (is_zero_v3(ob->dscale)) {
+ fill_vn_fl(ob->dscale, 3, 1.0f);
+ }
+ }
+ }
+
+ if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 8)) {
+ Brush *brush;
+
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ if (brush->sculpt_tool == SCULPT_TOOL_ROTATE)
+ brush->alpha = 1.0f;
+ }
+ }
+
+ if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 1)) {
+ {
+ /* update use flags for node sockets (was only temporary before) */
+ Scene *sce;
+ Material *mat;
+ Tex *tex;
+ Lamp *lamp;
+ World *world;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree)
+ do_versions_nodetree_socket_use_flags_2_62(sce->nodetree);
+ }
+
+ for (mat = main->mat.first; mat; mat = mat->id.next) {
+ if (mat->nodetree)
+ do_versions_nodetree_socket_use_flags_2_62(mat->nodetree);
+ }
+
+ for (tex = main->tex.first; tex; tex = tex->id.next) {
+ if (tex->nodetree)
+ do_versions_nodetree_socket_use_flags_2_62(tex->nodetree);
+ }
+
+ for (lamp = main->lamp.first; lamp; lamp = lamp->id.next) {
+ if (lamp->nodetree)
+ do_versions_nodetree_socket_use_flags_2_62(lamp->nodetree);
+ }
+
+ for (world = main->world.first; world; world = world->id.next) {
+ if (world->nodetree)
+ do_versions_nodetree_socket_use_flags_2_62(world->nodetree);
+ }
+
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ do_versions_nodetree_socket_use_flags_2_62(ntree);
+ }
+ }
+ {
+ /* Initialize BGE exit key to esc key */
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if (!scene->gm.exitkey)
+ scene->gm.exitkey = 218; // Blender key code for ESC
+ }
+ }
+ {
+ MovieClip *clip;
+ Object *ob;
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object = tracking->objects.first;
+
+ clip->proxy.build_tc_flag |= IMB_TC_RECORD_RUN_NO_GAPS;
+
+ if (!tracking->settings.object_distance)
+ tracking->settings.object_distance = 1.0f;
+
+ if (tracking->objects.first == NULL)
+ BKE_tracking_object_add(tracking, "Camera");
+
+ while (tracking_object) {
+ if (!tracking_object->scale)
+ tracking_object->scale = 1.0f;
+
+ tracking_object = tracking_object->next;
+ }
+ }
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bConstraint *con;
+ for (con = ob->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
+
+ if (data->invmat[3][3] == 0.0f)
+ unit_m4(data->invmat);
+ }
+ }
+ }
+ }
+ {
+ /* Warn the user if he is using ["Text"] properties for Font objects */
+ Object *ob;
+ bProperty *prop;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->type == OB_FONT) {
+ prop = BKE_bproperty_object_get(ob, "Text");
+ if (prop) {
+ blo_reportf_wrap(fd->reports, RPT_WARNING,
+ TIP_("Game property name conflict in object '%s': text objects reserve the "
+ "['Text'] game property to change their content through logic bricks"),
+ ob->id.name + 2);
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 2)) {
+ {
+ /* convert Camera Actuator values to defines */
+ Object *ob;
+ bActuator *act;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ for (act = ob->actuators.first; act; act = act->next) {
+ if (act->type == ACT_CAMERA) {
+ bCameraActuator *ba = act->data;
+
+ if (ba->axis == (float) 'x') ba->axis = OB_POSX;
+ else if (ba->axis == (float)'y') ba->axis = OB_POSY;
+ /* don't do an if/else to avoid imediate subversion bump*/
+// ba->axis=((ba->axis == (float)'x') ? OB_POSX_X : OB_POSY);
+ }
+ }
+ }
+ }
+
+ {
+ /* convert deprecated sculpt_paint_unified_* fields to
+ * UnifiedPaintSettings */
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ ToolSettings *ts = scene->toolsettings;
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->size = ts->sculpt_paint_unified_size;
+ ups->unprojected_radius = ts->sculpt_paint_unified_unprojected_radius;
+ ups->alpha = ts->sculpt_paint_unified_alpha;
+ ups->flag = ts->sculpt_paint_settings;
+ }
+ }
+ }
+
+ if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 3)) {
+ {
+ /* convert extended ascii to utf-8 for text editor */
+ Text *text;
+ for (text = main->text.first; text; text = text->id.next)
+ if (!(text->flags & TXT_ISEXT)) {
+ TextLine *tl;
+
+ for (tl = text->lines.first; tl; tl = tl->next) {
+ int added = txt_extended_ascii_as_utf8(&tl->line);
+ tl->len += added;
+
+ /* reset cursor position if line was changed */
+ if (added && tl == text->curl)
+ text->curc = 0;
+ }
+ }
+ }
+ {
+ /* set new dynamic paint values */
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_DynamicPaint) {
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
+ if (pmd->canvas) {
+ DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
+ for (; surface; surface = surface->next) {
+ surface->color_dry_threshold = 1.0f;
+ surface->influence_scale = 1.0f;
+ surface->radius_scale = 1.0f;
+ surface->flags |= MOD_DPAINT_USE_DRYING;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 262) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Cloth) {
+ ClothModifierData *clmd = (ClothModifierData *) md;
+ if (clmd->sim_parms)
+ clmd->sim_parms->vel_damping = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 263) {
+ /* set fluidsim rate. the version patch for this in 2.62 was wrong, so
+ * try to correct it, if rate is 0.0 that's likely not intentional */
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Fluidsim) {
+ FluidsimModifierData *fmd = (FluidsimModifierData *)md;
+ if (fmd->fss->animRate == 0.0f)
+ fmd->fss->animRate = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 1)) {
+ /* update use flags for node sockets (was only temporary before) */
+ Scene *sce;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree)
+ do_versions_nodetree_multi_file_output_format_2_62_1(sce, sce->nodetree);
+ }
+
+ /* XXX can't associate with scene for group nodes, image format will stay uninitialized */
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ do_versions_nodetree_multi_file_output_format_2_62_1(NULL, ntree);
+ }
+
+ /* only swap for pre-release bmesh merge which had MLoopCol red/blue swap */
+ if (main->versionfile == 262 && main->subversionfile == 1) {
+ {
+ Mesh *me;
+ for (me = main->mesh.first; me; me = me->id.next) {
+ do_versions_mesh_mloopcol_swap_2_62_1(me);
+ }
+ }
+ }
+
+ if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 2)) {
+ /* Set new idname of keyingsets from their now "label-only" name. */
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ KeyingSet *ks;
+ for (ks = scene->keyingsets.first; ks; ks = ks->next) {
+ if (!ks->idname[0])
+ BLI_strncpy(ks->idname, ks->name, sizeof(ks->idname));
+ }
+ }
+ }
+
+ if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 3)) {
+ Object *ob;
+ ModifierData *md;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Lattice) {
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ lmd->strength = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 4)) {
+ /* Read Viscosity presets from older files */
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Fluidsim) {
+ FluidsimModifierData *fmd = (FluidsimModifierData *)md;
+ if (fmd->fss->viscosityMode == 3) {
+ fmd->fss->viscosityValue = 5.0;
+ fmd->fss->viscosityExponent = 5;
+ }
+ else if (fmd->fss->viscosityMode == 4) {
+ fmd->fss->viscosityValue = 2.0;
+ fmd->fss->viscosityExponent = 3;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ if (main->versionfile < 263) {
+ /* Default for old files is to save particle rotations to pointcache */
+ ParticleSettings *part;
+ for (part = main->particle.first; part; part = part->id.next) {
+ part->flag |= PART_ROTATIONS;
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 1)) {
+ /* file output node paths are now stored in the file info struct instead socket name */
+ Scene *sce;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next)
+ if (sce->nodetree)
+ do_versions_nodetree_multi_file_output_path_2_63_1(sce->nodetree);
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ do_versions_nodetree_multi_file_output_path_2_63_1(ntree);
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 3)) {
+ Scene *scene;
+ Brush *brush;
+
+ /* For weight paint, each brush now gets its own weight;
+ * unified paint settings also have weight. Update unified
+ * paint settings and brushes with a default weight value. */
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ ToolSettings *ts = scene->toolsettings;
+ if (ts) {
+ ts->unified_paint_settings.weight = ts->vgroup_weight;
+ ts->unified_paint_settings.flag |= UNIFIED_PAINT_WEIGHT;
+ }
+ }
+
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ brush->weight = 0.5;
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 2)) {
+ bScreen *sc;
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = (SpaceClip *)sl;
+ ARegion *ar;
+ int hide = FALSE;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_PREVIEW) {
+ if (ar->alignment != RGN_ALIGN_NONE) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ ar->v2d.flag &= ~V2D_IS_INITIALISED;
+ ar->alignment = RGN_ALIGN_NONE;
+
+ hide = TRUE;
+ }
+ }
+ }
+
+ if (hide) {
+ sclip->view = SC_VIEW_CLIP;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 4)) {
+ Lamp *la;
+ Camera *cam;
+ Curve *cu;
+
+ for (la = main->lamp.first; la; la = la->id.next) {
+ if (la->shadow_frustum_size == 0.0f)
+ la->shadow_frustum_size = 10.0f;
+ }
+
+ for (cam = main->camera.first; cam; cam = cam->id.next) {
+ if (cam->flag & CAM_PANORAMA) {
+ cam->type = CAM_PANO;
+ cam->flag &= ~CAM_PANORAMA;
+ }
+ }
+
+ for (cu = main->curve.first; cu; cu = cu->id.next) {
+ if (cu->bevfac2 == 0.0f) {
+ cu->bevfac1 = 0.0f;
+ cu->bevfac2 = 1.0f;
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 5)) {
+ {
+ /* file output node paths are now stored in the file info struct instead socket name */
+ Scene *sce;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ do_versions_nodetree_file_output_layers_2_64_5(sce->nodetree);
+ do_versions_nodetree_image_layer_2_64_5(sce->nodetree);
+ }
+ }
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ do_versions_nodetree_file_output_layers_2_64_5(ntree);
+ do_versions_nodetree_image_layer_2_64_5(ntree);
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 6)) {
+ /* update use flags for node sockets (was only temporary before) */
+ Scene *sce;
+ Material *mat;
+ Tex *tex;
+ Lamp *lamp;
+ World *world;
+ bNodeTree *ntree;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next)
+ if (sce->nodetree)
+ do_versions_nodetree_frame_2_64_6(sce->nodetree);
+
+ for (mat = main->mat.first; mat; mat = mat->id.next)
+ if (mat->nodetree)
+ do_versions_nodetree_frame_2_64_6(mat->nodetree);
+
+ for (tex = main->tex.first; tex; tex = tex->id.next)
+ if (tex->nodetree)
+ do_versions_nodetree_frame_2_64_6(tex->nodetree);
+
+ for (lamp = main->lamp.first; lamp; lamp = lamp->id.next)
+ if (lamp->nodetree)
+ do_versions_nodetree_frame_2_64_6(lamp->nodetree);
+
+ for (world = main->world.first; world; world = world->id.next)
+ if (world->nodetree)
+ do_versions_nodetree_frame_2_64_6(world->nodetree);
+
+ for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ do_versions_nodetree_frame_2_64_6(ntree);
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 7)) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ int maxres = max_iii(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
+ smd->domain->scale = smd->domain->dx * maxres;
+ smd->domain->dx = 1.0f / smd->domain->scale;
+ }
+ }
+ }
+ }
+ }
+
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 8)) {
+ /* set new deactivation values for game settings */
+ Scene *sce;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ /* Game Settings */
+ sce->gm.lineardeactthreshold = 0.8f;
+ sce->gm.angulardeactthreshold = 1.0f;
+ sce->gm.deactivationtime = 2.0f;
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
+ NodeTexImage *tex = node->storage;
+
+ tex->iuser.frames = 1;
+ tex->iuser.sfra = 1;
+ tex->iuser.fie_ima = 2;
+ tex->iuser.ok = 1;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) {
+ {
+ Scene *scene;
+ // composite redesign
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if (scene->nodetree) {
+ if (scene->nodetree->chunksize == 0) {
+ scene->nodetree->chunksize = 256;
+ }
+ }
+ }
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DEFOCUS) {
+ NodeDefocus *data = node->storage;
+ if (data->maxblur == 0.0f) {
+ data->maxblur = 16.0f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ {
+ bScreen *sc;
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = (SpaceClip *)sl;
+
+ if (sclip->around == 0) {
+ sclip->around = V3D_CENTROID;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ {
+ MovieClip *clip;
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ clip->start_frame = 1;
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 11)) {
+ MovieClip *clip;
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTrackingTrack *track;
+
+ track = clip->tracking.tracks.first;
+ while (track) {
+ do_versions_affine_tracker_track(track);
+
+ track = track->next;
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 12)) {
+ Material *ma;
+
+ for (ma = main->mat.first; ma; ma = ma->id.next)
+ if (ma->strand_widthfade == 2.0f)
+ ma->strand_widthfade = 0.0f;
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DILATEERODE) {
+ if (node->storage == NULL) {
+ NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
+ data->falloff = PROP_SMOOTH;
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
+ ParticleSettings *part;
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_KEYING) {
+ NodeKeyingData *data = node->storage;
+
+ if (data->despill_balance == 0.0f) {
+ data->despill_balance = 0.5f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+
+ /* keep compatibility for dupliobject particle size */
+ for (part = main->particle.first; part; part = part->id.next)
+ if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
+ if ((part->draw & PART_DRAW_ROTATE_OB) == 0)
+ part->draw |= PART_DRAW_NO_SCALE_OB;
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_MASK) {
+ if (node->storage == NULL) {
+ NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
+ /* move settings into own struct */
+ data->size_x = (int)node->custom3;
+ data->size_y = (int)node->custom4;
+ node->custom3 = 0.5f; /* default shutter */
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) {
+ Scene *scene;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if (scene->ed) {
+ Sequence *seq;
+
+ SEQ_BEGIN (scene->ed, seq)
+ {
+ Strip *strip = seq->strip;
+
+ if (strip && strip->color_balance) {
+ SequenceModifierData *smd;
+ ColorBalanceModifierData *cbmd;
+
+ smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance);
+ cbmd = (ColorBalanceModifierData *) smd;
+
+ cbmd->color_balance = *strip->color_balance;
+
+ /* multiplication with color balance used is handled differently,
+ * so we need to move multiplication to modifier so files would be
+ * compatible
+ */
+ cbmd->color_multiply = seq->mul;
+ seq->mul = 1.0f;
+
+ MEM_freeN(strip->color_balance);
+ strip->color_balance = NULL;
+ }
+ }
+ SEQ_END
+ }
+ }
+ }
+
+ /* color management pipeline changes compatibility code */
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 19)) {
+ Scene *scene;
+ Image *ima;
+ int colormanagement_disabled = FALSE;
+
+ /* make scenes which are not using color management have got None as display device,
+ * so they wouldn't perform linear-to-sRGB conversion on display
+ */
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) {
+ ColorManagedDisplaySettings *display_settings = &scene->display_settings;
+
+ if (display_settings->display_device[0] == 0) {
+ BKE_scene_disable_color_management(scene);
+
+ }
+
+ colormanagement_disabled = TRUE;
+ }
+ }
+
+ for (ima = main->image.first; ima; ima = ima->id.next) {
+ if (ima->source == IMA_SRC_VIEWER) {
+ ima->flag |= IMA_VIEW_AS_RENDER;
+ }
+ else if (colormanagement_disabled) {
+ /* if colormanagement not used, set image's color space to raw, so no sRGB->linear conversion
+ * would happen on display and render
+ * there's no clear way to check whether color management is enabled or not in render engine
+ * so set all images to raw if there's at least one scene with color management disabled
+ * this would still behave incorrect in cases when color management was used for only some
+ * of scenes, but such a setup is crazy anyway and think it's fair enough to break compatibility
+ * in that cases
+ */
+
+ BLI_strncpy(ima->colorspace_settings.name, "Raw", sizeof(ima->colorspace_settings.name));
+ }
+ }
+ }
+
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 20)) {
+ Key *key;
+ for (key = main->key.first; key; key = key->id.next) {
+ blo_do_versions_key_uidgen(key);
+ }
+ }
+
+ /* remove texco */
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 21)) {
+ Material *ma;
+ for (ma = main->mat.first; ma; ma = ma->id.next) {
+ int a;
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a]) {
+ if (ma->mtex[a]->texco == TEXCO_STICKY_) {
+ ma->mtex[a]->texco = TEXCO_UV;
+ }
+ }
+ }
+ }
+
+ {
+ Mesh *me;
+ for (me = main->mesh.first; me; me = me->id.next) {
+ CustomData_update_typemap(&me->vdata);
+ CustomData_free_layers(&me->vdata, CD_MSTICKY, me->totvert);
+ }
+ }
+ }
+
+ /* correction for files saved in blender version when BKE_pose_copy_data
+ * didn't copy animation visualization, which lead to deadlocks on motion
+ * path calculation for proxied armatures, see [#32742]
+ */
+ if (main->versionfile < 264) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->pose) {
+ if (ob->pose->avs.path_step == 0) {
+ animviz_settings_init(&ob->pose->avs);
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->type == SH_NODE_TEX_COORD)
+ node->flag |= NODE_OPTIONS;
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) {
+ MovieClip *clip;
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object;
+
+ for (tracking_object = tracking->objects.first;
+ tracking_object;
+ tracking_object = tracking_object->next)
+ {
+ if (tracking_object->keyframe1 == 0 && tracking_object->keyframe2 == 0) {
+ tracking_object->keyframe1 = tracking->settings.keyframe1;
+ tracking_object->keyframe2 = tracking->settings.keyframe2;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 3)) {
+ /* smoke branch */
+ {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ /* keep branch saves if possible */
+ if (!smd->domain->flame_max_temp) {
+ smd->domain->burning_rate = 0.75f;
+ smd->domain->flame_smoke = 1.0f;
+ smd->domain->flame_vorticity = 0.5f;
+ smd->domain->flame_ignition = 1.25f;
+ smd->domain->flame_max_temp = 1.75f;
+ smd->domain->adapt_threshold = 0.02f;
+ smd->domain->adapt_margin = 4;
+ smd->domain->flame_smoke_color[0] = 0.7f;
+ smd->domain->flame_smoke_color[1] = 0.7f;
+ smd->domain->flame_smoke_color[2] = 0.7f;
+ }
+ }
+ else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
+ if (!smd->flow->texture_size) {
+ smd->flow->fuel_amount = 1.0;
+ smd->flow->surface_distance = 1.5;
+ smd->flow->color[0] = 0.7f;
+ smd->flow->color[1] = 0.7f;
+ smd->flow->color[2] = 0.7f;
+ smd->flow->texture_size = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* render border for viewport */
+ {
+ bScreen *sc;
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->render_border.xmin == 0.0f && v3d->render_border.ymin == 0.0f &&
+ v3d->render_border.xmax == 0.0f && v3d->render_border.ymax == 0.0f)
+ {
+ v3d->render_border.xmax = 1.0f;
+ v3d->render_border.ymax = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) {
+ /* set a unwrapping margin and ABF by default */
+ Scene *scene;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if (scene->toolsettings->uvcalc_margin == 0.0f) {
+ scene->toolsettings->uvcalc_margin = 0.001f;
+ scene->toolsettings->unwrapper = 0;
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
+ /* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
+ * Simply remove bad internal_links lists to avoid NULL pointers.
+ */
+ FOREACH_NODETREE(main, ntree, id) {
+ bNode *node;
+ bNodeLink *link, *nextlink;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (link = node->internal_links.first; link; link = nextlink) {
+ nextlink = link->next;
+ if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
+ BLI_remlink(&node->internal_links, link);
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
+ bScreen *sc;
+
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ if ( sa->spacetype == SPACE_LOGIC)
+ do_version_logic_264(&sa->regionbase);
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_LOGIC)
+ do_version_logic_264(&sl->regionbase);
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
+ /* convert tiles size from resolution and number of tiles */
+ {
+ Scene *scene;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if (scene->r.tilex == 0 || scene->r.tiley == 1) {
+ if (scene->r.xparts && scene->r.yparts) {
+ /* scene could be set for panoramic rendering, so clamp with the
+ * lowest possible tile size value
+ */
+ scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8);
+ scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8);
+ }
+ else {
+ /* happens when mixing using current trunk and previous release */
+ scene->r.tilex = scene->r.tiley = 64;
+ }
+ }
+ }
+ }
+
+ /* collision masks */
+ {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->col_group == 0) {
+ ob->col_group = 0x01;
+ ob->col_mask = 0xff;
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
+ MovieClip *clip;
+
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTrackingTrack *track;
+ MovieTrackingObject *object;
+
+ for (track = clip->tracking.tracks.first; track; track = track->next) {
+ do_versions_affine_tracker_track(track);
+ }
+
+ for (object = clip->tracking.objects.first; object; object = object->next) {
+ for (track = object->tracks.first; track; track = track->next) {
+ do_versions_affine_tracker_track(track);
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 265) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->step_height == 0.0f) {
+ ob->step_height = 0.15f;
+ ob->jump_speed = 10.0f;
+ ob->fall_speed = 55.0f;
+ }
+ }
+ }
+
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 3)) {
+ bScreen *sc;
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D *)sl;
+ v3d->flag2 |= V3D_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+ sseq->flag |= SEQ_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+ sima->flag |= SI_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+ snode->flag |= SNODE_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_CLIP:
+ {
+ SpaceClip *sclip = (SpaceClip *)sl;
+ sclip->flag |= SC_SHOW_GPENCIL;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
+ Scene *scene;
+ Image *image;
+ Tex *tex;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ Sequence *seq;
+ bool set_premul = false;
+
+ SEQ_BEGIN (scene->ed, seq)
+ {
+ if (seq->flag & SEQ_MAKE_PREMUL) {
+ seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+ }
+ else {
+ BKE_sequence_alpha_mode_from_extension(seq);
+ }
+ }
+ SEQ_END
+
+ if (scene->r.bake_samples == 0)
+ scene->r.bake_samples = 256;
+
+ if (scene->world) {
+ World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
+
+ if (world && is_zero_v3(&world->horr)) {
+ if ((world->skytype & WO_SKYBLEND) == 0 || is_zero_v3(&world->zenr)) {
+ set_premul = true;
+ }
+ }
+ }
+ else
+ set_premul = true;
+
+ if (set_premul) {
+ printf("2.66 versioning fix: replacing black sky with premultiplied alpha for scene %s\n",
+ scene->id.name + 2);
+ scene->r.alphamode = R_ALPHAPREMUL;
+ }
+ }
+
+ for (image = main->image.first; image; image = image->id.next) {
+ if (image->flag & IMA_DO_PREMUL) {
+ image->alpha_mode = IMA_ALPHA_STRAIGHT;
+ }
+ else {
+ BKE_image_alpha_mode_from_extension(image);
+ }
+ }
+
+ for (tex = main->tex.first; tex; tex = tex->id.next) {
+ if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
+ image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
+
+ if (image && (image->flag & IMA_DO_PREMUL) == 0)
+ image->flag |= IMA_IGNORE_ALPHA;
+ }
+ }
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_IMAGE) {
+ Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
+
+ if (image) {
+ if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
+ node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+ else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) {
+ /* texture use alpha was removed for 2.66 but added back again for 2.66a,
+ * for compatibility all textures assumed it to be enabled */
+ Tex *tex;
+
+ for (tex = main->tex.first; tex; tex = tex->id.next)
+ if (tex->type == TEX_IMAGE)
+ tex->imaflag |= TEX_USEALPHA;
+ }
+
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
+ Curve *cu;
+
+ for (cu = main->curve.first; cu; cu = cu->id.next) {
+ if (cu->flag & (CU_FRONT | CU_BACK)) {
+ if ( cu->ext1 != 0.0f || cu->ext2 != 0.0f) {
+ Nurb *nu;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ int a;
+
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+
+ while (a--) {
+ bezt->radius = 1.0f;
+ bezt++;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ bp->radius = 1.0f;
+ bp++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (MAIN_VERSION_OLDER(main, 265, 9)) {
+ Mesh *me;
+ for (me = main->mesh.first; me; me = me->id.next) {
+ BKE_mesh_do_versions_cd_flag_init(me);
+ }
+ }
+
+ if (MAIN_VERSION_OLDER(main, 265, 10)) {
+ Brush *br;
+ for (br = main->brush.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
+ br->mtex.brush_map_mode = MTEX_MAP_MODE_TILED;
+ }
+ }
+ }
+
+ // add storage for compositor translate nodes when not existing
+ if (MAIN_VERSION_OLDER(main, 265, 11)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
+ node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 2)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id));
+ } FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 2)) {
+ bScreen *sc;
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* reset pointers to force tree path update from context */
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ snode->id = NULL;
+ snode->from = NULL;
+
+ /* convert deprecated treetype setting to tree_idname */
+ switch (snode->treetype) {
+ case NTREE_COMPOSIT:
+ strcpy(snode->tree_idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(snode->tree_idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(snode->tree_idname, "TextureNodeTree");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */
+ {
+ FOREACH_NODETREE(main, ntree, id) {
+ /* XXX This should be kept without version check for now!
+ * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links
+ * to tree interface sockets for forward compatibility. These links need to be removed again
+ * on file load in new versions.
+ * Once forward compatibility is not required any longer, make a subversion bump
+ * and only execute this for older versions.
+ */
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP;
+
+ /* Only add interface nodes once.
+ * In old Blender versions they will be removed automatically due to undefined type */
+ if (MAIN_VERSION_OLDER(main, 266, 2))
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE;
+ }
+ FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 3)) {
+ {
+ /* Fix for a very old issue:
+ * Node names were nominally made unique in r24478 (2.50.8), but the do_versions check
+ * to update existing node names only applied to main->nodetree (i.e. group nodes).
+ * Uniqueness is now required for proper preview mapping,
+ * so do this now to ensure old files don't break.
+ */
+ bNode *node;
+ FOREACH_NODETREE(main, ntree, id) {
+ if (id == &ntree->id)
+ continue; /* already fixed for node groups */
+
+ for (node = ntree->nodes.first; node; node = node->next)
+ nodeUniqueName(ntree, node);
+ }
+ FOREACH_NODETREE_END
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 266, 4)) {
+ Brush *brush;
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ default_mtex(&brush->mask_mtex);
+
+ if (brush->ob_mode & OB_MODE_TEXTURE_PAINT) {
+ brush->spacing /= 2;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 266, 6)) {
+ Brush *brush;
+ #define BRUSH_TEXTURE_OVERLAY (1 << 21)
+
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ brush->overlay_flags = 0;
+ if (brush->flag & BRUSH_TEXTURE_OVERLAY)
+ brush->overlay_flags |= (BRUSH_OVERLAY_PRIMARY | BRUSH_OVERLAY_CURSOR);
+ }
+ #undef BRUSH_TEXTURE_OVERLAY
+ }
+
+ if (main->versionfile < 267) {
+ //if (!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "stencil_pos")) {
+ Brush *brush;
+
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ if (brush->stencil_dimension[0] == 0) {
+ brush->stencil_dimension[0] = 256;
+ brush->stencil_dimension[1] = 256;
+ brush->stencil_pos[0] = 256;
+ brush->stencil_pos[1] = 256;
+ }
+ if (brush->mask_stencil_dimension[0] == 0) {
+ brush->mask_stencil_dimension[0] = 256;
+ brush->mask_stencil_dimension[1] = 256;
+ brush->mask_stencil_pos[0] = 256;
+ brush->mask_stencil_pos[1] = 256;
+ }
+ }
+
+ /* TIP: to initialize new variables added, use the new function
+ * DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
+ * example:
+ * if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+ * user->image_gpubuffer_limit = 10;
+ */
+
+ }
+
+ /* default values in Freestyle settings */
+ if (main->versionfile < 267) {
+ Scene *sce;
+ SceneRenderLayer *srl;
+ FreestyleLineStyle *linestyle;
+
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->r.line_thickness_mode == 0) {
+ sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE;
+ sce->r.unit_line_thickness = 1.0f;
+ }
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ if (srl->freestyleConfig.mode == 0)
+ srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE;
+ if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
+ srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL)
+ {
+ srl->freestyleConfig.raycasting_algorithm = 0; /* deprecated */
+ srl->freestyleConfig.flags |= FREESTYLE_CULLING;
+ }
+ }
+
+ /* not freestyle */
+ {
+ MeshStatVis *statvis = &sce->toolsettings->statvis;
+ if (statvis->thickness_samples == 0) {
+ statvis->overhang_axis = OB_NEGZ;
+ statvis->overhang_min = 0;
+ statvis->overhang_max = DEG2RADF(45.0f);
+
+ statvis->thickness_max = 0.1f;
+ statvis->thickness_samples = 1;
+
+ statvis->distort_min = DEG2RADF(5.0f);
+ statvis->distort_max = DEG2RADF(45.0f);
+
+ statvis->sharp_min = DEG2RADF(90.0f);
+ statvis->sharp_max = DEG2RADF(180.0f);
+ }
+ }
+
+ }
+ for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+#if 1
+ /* disable the Misc panel for now */
+ if (linestyle->panel == LS_PANEL_MISC) {
+ linestyle->panel = LS_PANEL_STROKES;
+ }
+#endif
+ if (linestyle->thickness_position == 0) {
+ linestyle->thickness_position = LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio = 0.5f;
+ }
+ if (linestyle->chaining == 0)
+ linestyle->chaining = LS_CHAINING_PLAIN;
+ if (linestyle->rounds == 0)
+ linestyle->rounds = 3;
+ }
+ }
+
+ if (main->versionfile < 267) {
+ /* Initialize the active_viewer_key for compositing */
+ bScreen *screen;
+ Scene *scene;
+ bNodeInstanceKey active_viewer_key = {0};
+ /* simply pick the first node space and use that for the active viewer key */
+ for (screen = main->screen.first; screen; screen = screen->id.next) {
+ ScrArea *sa;
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path = snode->treepath.last;
+ if (!path)
+ continue;
+
+ active_viewer_key = path->parent_key;
+ break;
+ }
+ }
+ if (active_viewer_key.value != 0)
+ break;
+ }
+ if (active_viewer_key.value != 0)
+ break;
+ }
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ /* NB: scene->nodetree is a local ID block, has been direct_link'ed */
+ if (scene->nodetree)
+ scene->nodetree->active_viewer_key = active_viewer_key;
+ }
+ }
+
+ if (MAIN_VERSION_OLDER(main, 267, 1)) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+ if (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) {
+ smd->domain->highres_sampling = SM_HRES_LINEAR;
+ }
+ else {
+ smd->domain->highres_sampling = SM_HRES_NEAREST;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 1)) {
+ Brush *brush;
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ brush->spacing = MAX2(1, brush->spacing);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 2)) {
+ Brush *brush;
+ #define BRUSH_FIXED (1 << 6)
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ brush->flag &= ~BRUSH_FIXED;
+
+ if (brush->cursor_overlay_alpha < 2)
+ brush->cursor_overlay_alpha = 33;
+ if (brush->texture_overlay_alpha < 2)
+ brush->texture_overlay_alpha = 33;
+ if (brush->mask_overlay_alpha < 2)
+ brush->mask_overlay_alpha = 33;
+ }
+ #undef BRUSH_FIXED
+ }
+
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 4)) {
+ bScreen *sc;
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bConstraint *con;
+ for (con = ob->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
+ bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)con->data;
+ if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) data->projAxis = OB_POSX;
+ else if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) data->projAxis = OB_POSY;
+ else data->projAxis = OB_POSZ;
+ data->projAxisSpace = CONSTRAINT_SPACE_LOCAL;
+ }
+ }
+ }
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
+ if (!smd->flow->particle_size) {
+ smd->flow->particle_size = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * FIX some files have a zoom level of 0, and was checked during the drawing of the node space
+ *
+ * We moved this check to the do versions to be sure the value makes any sense.
+ */
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ if (snode->zoom < 0.02f) {
+ snode->zoom = 1.0;
+ }
+ }
+ }
+ }
+ }
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bSensor *sens;
+ bTouchSensor *ts;
+ bCollisionSensor *cs;
+ Material *ma;
+
+ for (sens = ob->sensors.first; sens; sens = sens->next) {
+ if (sens->type == SENS_TOUCH) {
+ ts = sens->data;
+ cs = MEM_callocN(sizeof(bCollisionSensor), "touch -> collision sensor do_version");
+
+ if (ts->ma) {
+ ma = blo_do_versions_newlibadr(fd, ob->id.lib, ts->ma);
+ BLI_strncpy(cs->materialName, ma->id.name + 2, sizeof(cs->materialName));
+ }
+
+ cs->mode = SENS_COLLISION_MATERIAL;
+
+ MEM_freeN(ts);
+
+ sens->data = cs;
+ sens->type = sens->otype = SENS_COLLISION;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 5)) {
+ bScreen *sc;
+ ScrArea *sa;
+
+ /* add missing (+) expander in node editor */
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ARegion *ar, *arnew;
+
+ if (sa->spacetype == SPACE_NODE) {
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+
+ if (ar)
+ continue;
+
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+
+ /* is error! */
+ if (ar == NULL)
+ continue;
+
+ arnew = MEM_callocN(sizeof(ARegion), "node tools");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 1)) {
+ /* Removal of Cycles SSS Compatible falloff */
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
+ if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) {
+ node->custom1 = SHD_SUBSURFACE_CUBIC;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 2)) {
+ /* Initialize CDL settings for Color Balance nodes */
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_COLORBALANCE) {
+ NodeColorBalance *n = node->storage;
+ if (node->custom1 == 0) {
+ /* LGG mode stays the same, just init CDL settings */
+ ntreeCompositColorBalanceSyncFromLGG(ntree, node);
+ }
+ else if (node->custom1 == 1) {
+ /* CDL previously used same variables as LGG, copy them over
+ * and then sync LGG for comparable results in both modes.
+ */
+ copy_v3_v3(n->offset, n->lift);
+ copy_v3_v3(n->power, n->gamma);
+ copy_v3_v3(n->slope, n->gain);
+ ntreeCompositColorBalanceSyncFromCDL(ntree, node);
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 3)) {
+ bScreen *sc;
+ ScrArea *sa;
+ SpaceLink *sl;
+ Scene *scene;
+
+ /* Update files using invalid (outdated) outlinevis Outliner values. */
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOops *so = (SpaceOops *)sl;
+
+ if (!ELEM11(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
+ SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
+ SO_USERDEF))
+ {
+ so->outlinevis = SO_ALL_SCENES;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingTrack", "float", "weight")) {
+ MovieClip *clip;
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *tracking_object;
+ for (tracking_object = tracking->objects.first;
+ tracking_object;
+ tracking_object = tracking_object->next)
+ {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track;
+ for (track = tracksbase->first;
+ track;
+ track = track->next)
+ {
+ track->weight = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "TriangulateModifierData", "int", "quad_method")) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Triangulate) {
+ TriangulateModifierData *tmd = (TriangulateModifierData *)md;
+ if ((tmd->flag & MOD_TRIANGULATE_BEAUTY)) {
+ tmd->quad_method = MOD_TRIANGULATE_QUAD_BEAUTY;
+ tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY;
+ }
+ else {
+ tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
+ tmd->ngon_method = MOD_TRIANGULATE_NGON_SCANFILL;
+ }
+ }
+ }
+ }
+ }
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ /* this can now be turned off */
+ ToolSettings *ts = scene->toolsettings;
+ if (ts->sculpt)
+ ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE;
+
+ /* single texture mode removed from game engine */
+ if (scene->gm.matmode == GAME_MAT_TEXFACE)
+ scene->gm.matmode = GAME_MAT_MULTITEX;
+
+ /* 'Increment' mode disabled for nodes, use true grid snapping instead */
+ if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_INCREMENT)
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
+
+#ifdef WITH_FFMPEG
+ /* Update for removed "sound-only" option in FFMPEG export settings. */
+ if (scene->r.ffcodecdata.type >= FFMPEG_INVALID) {
+ scene->r.ffcodecdata.type = FFMPEG_AVI;
+ }
+#endif
+
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 4)) {
+ /* Internal degrees to radians conversions... */
+ {
+ Scene *scene;
+ Object *ob;
+ Lamp *lamp;
+
+ for (lamp = main->lamp.first; lamp; lamp = lamp->id.next)
+ lamp->spotsize = DEG2RADF(lamp->spotsize);
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ bSensor *bs;
+ bActuator *ba;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_EdgeSplit) {
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData *)md;
+ emd->split_angle = DEG2RADF(emd->split_angle);
+ }
+ else if (md->type == eModifierType_Bevel) {
+ BevelModifierData *bmd = (BevelModifierData *)md;
+ bmd->bevel_angle = DEG2RADF(bmd->bevel_angle);
+ }
+ }
+
+ for (bs = ob->sensors.first; bs; bs = bs->next) {
+ if (bs->type == SENS_RADAR) {
+ bRadarSensor *brs = bs->data;
+ brs->angle = DEG2RADF(brs->angle);
+ }
+ }
+
+ for (ba = ob->actuators.first; ba; ba = ba->next) {
+ if (ba->type == ACT_CONSTRAINT) {
+ bConstraintActuator *bca = ba->data;
+ if (bca->type == ACT_CONST_TYPE_ORI) {
+ bca->minloc[0] = DEG2RADF(bca->minloc[0]);
+ bca->maxloc[0] = DEG2RADF(bca->maxloc[0]);
+ }
+ }
+ else if (ba->type == ACT_SOUND) {
+ bSoundActuator *bsa = ba->data;
+ bsa->sound3D.cone_outer_angle = DEG2RADF(bsa->sound3D.cone_outer_angle);
+ bsa->sound3D.cone_inner_angle = DEG2RADF(bsa->sound3D.cone_inner_angle);
+ }
+ }
+ }
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ Sequence *seq;
+ SEQ_BEGIN (scene->ed, seq)
+ {
+ if (seq->type == SEQ_TYPE_WIPE) {
+ WipeVars *wv = seq->effectdata;
+ wv->angle = DEG2RADF(wv->angle);
+ }
+ }
+ SEQ_END
+ }
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_BOKEHIMAGE) {
+ NodeBokehImage *n = node->storage;
+ n->angle = DEG2RADF(n->angle);
+ }
+ if (node->type == CMP_NODE_MASK_BOX) {
+ NodeBoxMask *n = node->storage;
+ n->rotation = DEG2RADF(n->rotation);
+ }
+ if (node->type == CMP_NODE_MASK_ELLIPSE) {
+ NodeEllipseMask *n = node->storage;
+ n->rotation = DEG2RADF(n->rotation);
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingPlaneTrack", "float", "image_opacity")) {
+ MovieClip *clip;
+ for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ MovieTrackingPlaneTrack *plane_track;
+ for (plane_track = clip->tracking.plane_tracks.first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ plane_track->image_opacity = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 7)) {
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ Sculpt *sd = scene->toolsettings->sculpt;
+
+ if (sd) {
+ int symmetry_flags = sd->flags & 7;
+
+ if (symmetry_flags & SCULPT_SYMM_X)
+ sd->paint.symmetry_flags |= PAINT_SYMM_X;
+ if (symmetry_flags & SCULPT_SYMM_Y)
+ sd->paint.symmetry_flags |= PAINT_SYMM_Y;
+ if (symmetry_flags & SCULPT_SYMM_Z)
+ sd->paint.symmetry_flags |= PAINT_SYMM_Z;
+ if (symmetry_flags & SCULPT_SYMMETRY_FEATHER)
+ sd->paint.symmetry_flags |= PAINT_SYMMETRY_FEATHER;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 6a0f1747d2f..82fa58b57e1 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -46,6 +46,7 @@ void BLO_update_defaults_startup_blend(Main *main)
for (scene = main->scene.first; scene; scene = scene->id.next) {
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+ scene->r.im_format.compress = 15;
for (srl = scene->r.layers.first; srl; srl = srl->next)
srl->freestyleConfig.sphere_radius = 0.1f;
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 067a8629906..e90a635db90 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -3079,7 +3079,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
part->id.flag |= (ob->id.flag & LIB_NEED_LINK);
psys->totpart = 0;
- psys->flag = PSYS_ENABLED|PSYS_CURRENT;
+ psys->flag = PSYS_CURRENT;
BLI_addtail(&ob->particlesystem, psys);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 83346dc8b04..398847348cc 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1476,8 +1476,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
}
else if(md->type==eModifierType_LaplacianDeform) {
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData*) md;
-
- writedata(wd, DATA, sizeof(float)*lmd->total_verts*3, lmd->vertexco);
+
+ writedata(wd, DATA, sizeof(float)*lmd->total_verts * 3, lmd->vertexco);
}
}
}
@@ -3479,7 +3479,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
BLI_cleanup_dir(mainvar->name, dir1);
BLI_cleanup_dir(mainvar->name, dir2);
- if (BLI_path_cmp(dir1, dir2)==0) {
+ if (G.relbase_valid && (BLI_path_cmp(dir1, dir2) == 0)) {
write_flags &= ~G_FILE_RELATIVE_REMAP;
}
else {
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index b80a10b43fe..afb8b07b1a6 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -31,7 +31,6 @@ set(INC
../makesdna
../../../intern/guardedalloc
../../../extern/rangetree
- ../../../intern/opennl/extern
)
set(INC_SYS
@@ -160,6 +159,13 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_OPENNL)
+ add_definitions(-DWITH_OPENNL)
+ list(APPEND INC_SYS
+ ../../../intern/opennl/extern
+ )
+endif()
+
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 0726af4b641..a270830e469 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -2294,7 +2294,7 @@ BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep)
* low level function so both face pointers remain intact but point to swapped data.
* \note must be from the same bmesh.
*/
-void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b)
+void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
{
BMLoop *l_iter, *l_first;
@@ -2311,5 +2311,8 @@ void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b)
} while ((l_iter = l_iter->next) != l_first);
SWAP(BMFace, (*f_a), (*f_b));
- bm->elem_index_dirty |= BM_FACE;
+
+ /* swap back */
+ SWAP(void *, f_a->head.data, f_b->head.data);
+ SWAP(int, f_a->head.index, f_b->head.index);
}
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 9e33509c2c8..e9fd4e650cb 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -87,6 +87,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
-void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b);
+void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
#endif /* __BMESH_CORE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 611ee4d03b8..b4439703c4a 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -238,6 +238,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
#ifdef DEBUG
BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname);
+
+ /* avoid accidental re-use */
+ memset(op, 0xff, sizeof(*op));
#else
(void)bm;
#endif
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 3db6ba0e7c9..e65c3fc578d 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -36,7 +36,7 @@
#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_scanfill.h"
+#include "BLI_polyfill2d.h"
#include "BLI_listbase.h"
#include "bmesh.h"
@@ -176,22 +176,19 @@ static void bm_face_calc_poly_center_mean_vertex_cos(BMFace *f, float r_cent[3],
* \param r_loops Store face loop pointers, (f->len)
* \param r_index Store triangle triples, indicies into \a r_loops, ((f->len - 2) * 3)
*/
-int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*_r_index)[3])
+void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3])
{
- int *r_index = (int *)_r_index;
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter;
- int totfilltri;
if (f->len == 3) {
*r_loops++ = (l_iter = l_first);
*r_loops++ = (l_iter = l_iter->next);
*r_loops++ = ( l_iter->next);
- r_index[0] = 0;
- r_index[1] = 1;
- r_index[2] = 2;
- totfilltri = 1;
+ r_index[0][0] = 0;
+ r_index[0][1] = 1;
+ r_index[0][2] = 2;
}
else if (f->len == 4) {
*r_loops++ = (l_iter = l_first);
@@ -199,72 +196,32 @@ int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*_r_index)
*r_loops++ = (l_iter = l_iter->next);
*r_loops++ = ( l_iter->next);
- r_index[0] = 0;
- r_index[1] = 1;
- r_index[2] = 2;
+ r_index[0][0] = 0;
+ r_index[0][1] = 1;
+ r_index[0][2] = 2;
- r_index[3] = 0;
- r_index[4] = 2;
- r_index[5] = 3;
- totfilltri = 2;
+ r_index[1][0] = 0;
+ r_index[1][1] = 2;
+ r_index[1][2] = 3;
}
else {
+ float axis_mat[3][3];
+ float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
int j;
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
- /* ScanFillEdge *e; */ /* UNUSED */
- ScanFillFace *sf_tri;
-
- BLI_scanfill_begin(&sf_ctx);
+ axis_dominant_v3_to_m3(axis_mat, f->no);
j = 0;
l_iter = l_first;
do {
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
- sf_vert->tmp.p = l_iter;
-
- if (sf_vert_last) {
- /* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
- }
-
- sf_vert_last = sf_vert;
- if (sf_vert_first == NULL) {
- sf_vert_first = sf_vert;
- }
-
+ mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
r_loops[j] = l_iter;
-
- /* mark order */
- BM_elem_index_set(l_iter, j++); /* set_loop */
-
+ j++;
} while ((l_iter = l_iter->next) != l_first);
/* complete the loop */
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
-
- totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no);
- BLI_assert(totfilltri <= f->len - 2);
- BLI_assert(totfilltri == BLI_countlist(&sf_ctx.fillfacebase));
-
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- int i1 = BM_elem_index_get((BMLoop *)sf_tri->v1->tmp.p);
- int i2 = BM_elem_index_get((BMLoop *)sf_tri->v2->tmp.p);
- int i3 = BM_elem_index_get((BMLoop *)sf_tri->v3->tmp.p);
-
- if (i1 > i2) { SWAP(int, i1, i2); }
- if (i2 > i3) { SWAP(int, i2, i3); }
- if (i1 > i2) { SWAP(int, i1, i2); }
-
- *r_index++ = i1;
- *r_index++ = i2;
- *r_index++ = i3;
- }
-
- BLI_scanfill_end(&sf_ctx);
+ BLI_polyfill_calc((const float (*)[2])projverts, f->len, r_index);
}
-
- return totfilltri;
}
/**
@@ -808,17 +765,22 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3])
* \brief BMESH TRIANGULATE FACE
*
* Breaks all quads and ngons down to triangles.
- * It uses scanfill for the ngons splitting, and
+ * It uses polyfill for the ngons splitting, and
* the beautify operator when use_beauty is true.
*
* \param r_faces_new if non-null, must be an array of BMFace pointers,
* with a length equal to (f->len - 3). It will be filled with the new
* triangles (not including the original triangle).
*
+ * \note The number of faces is _almost_ always (f->len - 3),
+ * However there may be faces that already occupying the
+ * triangles we would make, so the caller must check \a r_faces_new_tot.
+ *
* \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,
@@ -832,10 +794,10 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
int edge_array_len;
bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
-#define SF_EDGE_IS_BOUNDARY 0xff
-
BLI_assert(BM_face_is_normal_valid(f));
+ /* ensure both are valid or NULL */
+ BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL));
if (f->len == 4) {
BMVert *v1, *v2;
@@ -911,47 +873,37 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
}
}
else if (f->len > 4) {
- /* scanfill */
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert, *sf_vert_prev = NULL;
- ScanFillEdge *sf_edge;
- ScanFillFace *sf_tri;
- int totfilltri;
-
- /* populate scanfill */
- BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-
- /* step once before entering the loop */
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
- sf_vert->tmp.p = l_iter;
- sf_vert_prev = sf_vert;
- l_iter = l_iter->next;
- do {
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
- sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert);
- sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
+ float axis_mat[3][3];
+ float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ unsigned int (*tris)[3] = BLI_array_alloca(tris, f->len);
+ const int totfilltri = f->len - 2;
+ const int last_tri = f->len - 3;
+ int i;
- sf_vert->tmp.p = l_iter;
- sf_vert_prev = sf_vert;
- } while ((l_iter = l_iter->next) != l_first);
+ axis_dominant_v3_to_m3(axis_mat, f->no);
- sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_ctx.fillvertbase.first);
- sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY;
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+ loops[i] = l_iter;
+ mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
+ }
- /* calculate filled triangles */
- totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no);
- BLI_assert(totfilltri <= f->len - 2);
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, tris,
+ sf_arena);
+ if (use_beauty) {
+ edge_array = BLI_array_alloca(edge_array, orig_f_len - 3);
+ edge_array_len = 0;
+ }
/* loop over calculated triangles and create new geometry */
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ for (i = 0; i < totfilltri; i++) {
/* the order is reverse, otherwise the normal is flipped */
BMLoop *l_tri[3] = {
- sf_tri->v3->tmp.p,
- sf_tri->v2->tmp.p,
- sf_tri->v1->tmp.p};
+ loops[tris[i][2]],
+ loops[tris[i][1]],
+ loops[tris[i][0]]};
BMVert *v_tri[3] = {
l_tri[0]->v,
@@ -969,7 +921,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev);
/* add all but the last face which is swapped and removed (below) */
- if (sf_tri->next) {
+ if (i != last_tri) {
if (use_tag) {
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
}
@@ -977,46 +929,43 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
r_faces_new[nf_i++] = f_new;
}
}
- }
- if (use_beauty || use_tag) {
- ScanFillEdge *sf_edge;
- edge_array = BLI_array_alloca(edge_array, orig_f_len - 3);
- edge_array_len = 0;
-
- for (sf_edge = sf_ctx.filledgebase.first; sf_edge; sf_edge = sf_edge->next) {
- BMLoop *l1 = sf_edge->v1->tmp.p;
- BMLoop *l2 = sf_edge->v2->tmp.p;
-
- BMEdge *e = BM_edge_exists(l1->v, l2->v);
- if (sf_edge->tmp.c != SF_EDGE_IS_BOUNDARY) {
+ /* we know any edge that we create and _isnt_ */
+ if (use_beauty || use_tag) {
+ /* new faces loops */
+ l_iter = l_first = l_new;
+ do {
+ BMEdge *e = l_iter->e;
+ /* confusing! if its not a boundary now, we know it will be later
+ * since this will be an edge of one of the new faces which we're in the middle of creating */
+ 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_beauty) {
- BM_elem_index_set(e, edge_array_len); /* set_dirty */
- edge_array[edge_array_len] = e;
- edge_array_len++;
- }
+ if (use_tag) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
- if (use_tag) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
}
- }
- else if (use_tag) {
- BM_elem_flag_disable(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(bm, f, f_new);
+ bmesh_face_swap_data(f, f_new);
BM_face_kill(bm, f_new);
}
if (use_beauty) {
- bm->elem_index_dirty |= BM_EDGE;
+ 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) {
@@ -1067,21 +1016,19 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
#undef FACE_USED_SET
/* nf_i doesn't include the last face */
- BLI_assert(nf_i == orig_f_len - 3);
+ 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(bm, f, f_new);
+ bmesh_face_swap_data(f, f_new);
BM_face_kill(bm, f_new);
}
}
-
- /* garbage collection */
- BLI_scanfill_end_arena(&sf_ctx, sf_arena);
}
-#undef SF_EDGE_IS_BOUNDARY
-
+ if (r_faces_new_tot) {
+ *r_faces_new_tot = nf_i;
+ }
}
/**
@@ -1290,11 +1237,9 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
BMIter iter;
BMFace *efa;
- BMLoop *l;
int i = 0;
- ScanFillContext sf_ctx;
- MemArena *sf_arena = NULL;
+ MemArena *arena = NULL;
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
/* don't consider two-edged faces */
@@ -1315,6 +1260,7 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
i += 1;
#else
/* more cryptic but faster */
+ BMLoop *l;
BMLoop **l_ptr = looptris[i++];
l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
l_ptr[1] = l = l->next;
@@ -1341,6 +1287,7 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
i += 1;
#else
/* more cryptic but faster */
+ BMLoop *l;
BMLoop **l_ptr_a = looptris[i++];
BMLoop **l_ptr_b = looptris[i++];
(l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
@@ -1354,73 +1301,56 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
else {
int j;
+
BMLoop *l_iter;
BMLoop *l_first;
+ BMLoop **l_arr;
+
+ float axis_mat[3][3];
+ float (*projverts)[2];
+ unsigned int (*tris)[3];
- ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
- /* ScanFillEdge *e; */ /* UNUSED */
- ScanFillFace *sf_tri;
- int totfilltri;
+ const int totfilltri = efa->len - 2;
- if (UNLIKELY(sf_arena == NULL)) {
- sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+ if (UNLIKELY(arena == NULL)) {
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
- BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
+ tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri);
+ l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len);
+ projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len);
+
+ axis_dominant_v3_to_m3(axis_mat, efa->no);
- /* scanfill time */
j = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
- sf_vert->tmp.p = l_iter;
-
- if (sf_vert_last) {
- /* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
- }
-
- sf_vert_last = sf_vert;
- if (sf_vert_first == NULL) {
- sf_vert_first = sf_vert;
- }
-
- /*mark order */
- BM_elem_index_set(l_iter, j++); /* set_loop */
-
+ l_arr[j] = l_iter;
+ mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
+ j++;
} while ((l_iter = l_iter->next) != l_first);
- /* complete the loop */
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
-
- totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
- BLI_assert(totfilltri <= efa->len - 2);
- (void)totfilltri;
+ BLI_polyfill_calc_arena((const float (*)[2])projverts, efa->len, tris, arena);
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ for (j = 0; j < totfilltri; j++) {
BMLoop **l_ptr = looptris[i++];
- BMLoop *l1 = sf_tri->v1->tmp.p;
- BMLoop *l2 = sf_tri->v2->tmp.p;
- BMLoop *l3 = sf_tri->v3->tmp.p;
-
- if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
- if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop *, l2, l3); }
- if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
+ unsigned int *tri = tris[j];
- l_ptr[0] = l1;
- l_ptr[1] = l2;
- l_ptr[2] = l3;
+ l_ptr[0] = l_arr[tri[2]];
+ l_ptr[1] = l_arr[tri[1]];
+ l_ptr[2] = l_arr[tri[0]];
}
- BLI_scanfill_end_arena(&sf_ctx, sf_arena);
+ BLI_memarena_clear(arena);
}
}
- if (sf_arena) {
- BLI_memarena_free(sf_arena);
- sf_arena = NULL;
+ if (arena) {
+ BLI_memarena_free(arena);
+ arena = NULL;
}
- *r_looptris_tot = looptris_tot;
+ *r_looptris_tot = i;
BLI_assert(i <= looptris_tot);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 4b3b7f4b837..f408947f467 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -31,7 +31,7 @@
void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
-int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*r_index)[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]);
void BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
void BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
@@ -54,7 +54,9 @@ 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 **newfaces,
+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);
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 9b4f34d18f2..e5acd19f927 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -1886,13 +1886,12 @@ bool BM_face_is_normal_valid(const BMFace *f)
static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol)
{
- int tottri = f->len - 2;
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- int (*index)[3] = BLI_array_alloca(index, tottri);
+ 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;
- tottri = BM_face_calc_tessellation(f, loops, index);
- BLI_assert(tottri <= f->len - 2);
+ BM_face_calc_tessellation(f, loops, index);
for (j = 0; j < tottri; j++) {
const float *p1 = loops[index[j][0]]->v->co;
diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c
index d9ab30bfcfa..4a292c33472 100644
--- a/source/blender/bmesh/operators/bmo_beautify.c
+++ b/source/blender/bmesh/operators/bmo_beautify.c
@@ -71,13 +71,10 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_test(bm, e->l->f, FACE_MARK) &&
BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK))
{
- BM_elem_index_set(e, edge_array_len); /* set_dirty */
- BM_elem_flag_enable(e, BM_ELEM_TAG);
edge_array[edge_array_len] = e;
edge_array_len++;
}
}
- bm->elem_index_dirty |= BM_EDGE;
BM_mesh_beautify_fill(bm, edge_array, edge_array_len, flag, method, ELE_NEW, FACE_MARK | ELE_NEW);
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 10d15d93995..9e9cd0d66e2 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -484,7 +484,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false);
const int twist_offset = BMO_slot_int_get(op->slots_in, "twist_offset");
int count;
- bool change = false;
+ bool changed = false;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
@@ -546,13 +546,13 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
if (use_pairs) {
el_store = el_store->next;
}
- change = true;
+ changed = true;
}
cleanup:
BM_mesh_edgeloops_free(&eloops);
- if (change) {
+ if (changed) {
if (use_merge == false) {
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index cf36e88ea98..ae645b97874 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -440,13 +440,18 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, msg);
}
- /* clean up any remainin */
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ /* clean up any remaining */
+ /* note: don't use BM_ITER_MESH_MUTABLE here, even though vertices are removed (T37559) */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (!BM_vert_dissolve(bm, v)) {
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
return;
}
+#ifdef DEBUG
+ /* workaround debug assert */
+ iter.count = bm->totvert;
+#endif
}
}
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 50d25202f7e..6a0fca425f8 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -594,7 +594,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
int count;
- bool change = false;
+ bool changed = false;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm);
@@ -690,14 +690,14 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
bm_grid_fill(bm, estore_a, estore_b, estore_rail_a, estore_rail_b,
mat_nr, use_smooth, use_interp_simple);
- change = true;
+ changed = true;
cleanup:
BM_mesh_edgeloops_free(&eloops);
BM_mesh_edgeloops_free(&eloops_rail);
- if (change) {
+ if (changed) {
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
}
}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 6a540928d43..34e4efbe562 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -228,67 +228,54 @@ static signed char monkeyf[250][4] = {
void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
{
+ BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out");
+
const float dia = BMO_slot_float_get(op->slots_in, "size");
- const int tot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
- const int seg = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
+ const unsigned int xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
+ const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
+ const float xtot_inv2 = 2.0f / (xtot - 1);
+ const float ytot_inv2 = 2.0f / (ytot - 1);
- BMOperator bmop, prevop;
- BMVert *eve, *preveve;
- BMEdge *e;
- float vec[3], mat[4][4], phi, phid;
- int a;
+ BMVert **varr;
+ BMVert *vquad[4];
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+ float mat[4][4];
+ float vec[3], tvec[3];
- /* one segment first: the X axis */
- phi = 1.0f;
- phid = 2.0f / ((float)tot - 1);
- for (a = 0; a < tot; a++) {
- vec[0] = dia * phi;
- vec[1] = -dia;
- vec[2] = 0.0f;
- mul_m4_v3(mat, vec);
+ unsigned int x, y, i;
- eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, eve, VERT_MARK);
- if (a != 0) {
- e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(bm, e, EDGE_ORIG);
- }
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- preveve = eve;
- phi -= phid;
+ BMO_slot_buffer_alloc(op, op->slots_out, "verts.out", xtot * ytot);
+ varr = (BMVert **)slot_verts_out->data.buf;
+
+ i = 0;
+ vec[2] = 0.0f;
+ for (y = 0; y < ytot; y++) {
+ vec[1] = ((y * ytot_inv2) - 1.0f) * dia;
+ for (x = 0; x < xtot; x++) {
+ vec[0] = ((x * xtot_inv2) - 1.0f) * dia;
+ mul_v3_m4v3(tvec, mat, vec);
+ varr[i++] = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ }
}
- /* extrude and translate */
- phid = 2.0f / ((float)seg - 1);
- vec[0] = vec[2] = 0.0f;
- vec[1] = dia * phid;
- mul_mat3_m4_v3(mat, vec);
+#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
- for (a = 0; a < seg - 1; a++) {
- if (a) {
- BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out");
- BMO_op_exec(bm, &bmop);
- BMO_op_finish(bm, &prevop);
+ for (y = 1; y < ytot; y++) {
+ for (x = 1; x < xtot; x++) {
+ vquad[0] = varr[XY(x - 1, y - 1)];
+ vquad[1] = varr[XY(x, y - 1)];
+ vquad[2] = varr[XY(x, y)];
+ vquad[3] = varr[XY(x - 1, y)];
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
+ BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
}
- else {
- BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG);
- BMO_op_exec(bm, &bmop);
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
- }
-
- BMO_op_callf(bm, op->flag, "translate vec=%v verts=%S", vec, &bmop, "geom.out");
- prevop = bmop;
}
- if (a)
- BMO_op_finish(bm, &bmop);
+#undef XY
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
@@ -301,8 +288,9 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
BMVert *eve, *preveve;
BMEdge *e;
BMIter iter;
- float vec[3], mat[4][4], cmat[3][3], phi, q[4];
- float phid;
+ const float axis[3] = {0, 0, 1};
+ float vec[3], mat[4][4], cmat[3][3];
+ float phi, phid;
int a;
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
@@ -331,11 +319,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
}
/* extrude and rotate; negative phi to make normals face outward */
- phi = -M_PI / seg;
- q[0] = cosf(phi);
- q[3] = sinf(phi);
- q[1] = q[2] = 0.0f;
- quat_to_mat3(cmat, q);
+ axis_angle_to_mat3(cmat, axis, -(M_PI * 2) / seg);
for (a = 0; a < seg; a++) {
if (a) {
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 3f04e23aa73..16e70e8c155 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -34,10 +34,12 @@
#include "bmesh.h"
-#include "ONL_opennl.h"
-
#include "intern/bmesh_operators_private.h" /* own include */
+#ifdef WITH_OPENNL
+
+#include "ONL_opennl.h"
+
// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */
// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */
#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f
@@ -572,3 +574,13 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
delete_laplacian_system(sys);
}
+
+#else /* WITH_OPENNL */
+
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) {}
+
+#endif /* WITH_OPENNL */
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index 13a7aa09335..d1ec06c5486 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -1070,7 +1070,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
BMOIter siter;
BMEdge *e;
int count;
- bool change = false;
+ bool changed = false;
const int cuts = BMO_slot_int_get(op->slots_in, "cuts");
const int interp_mode = BMO_slot_int_get(op->slots_in, "interp_mode");
@@ -1166,7 +1166,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
bm_edgering_pair_ringsubd(bm, lpair, el_store_a, el_store_b,
interp_mode, cuts, smooth, falloff_cache);
bm_edgering_pair_store_free(lpair, interp_mode);
- change = true;
+ changed = true;
}
else {
BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
@@ -1217,7 +1217,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
bm_edgering_pair_ringsubd(bm, lpair, el_store_a, el_store_b,
interp_mode, cuts, smooth, falloff_cache);
bm_edgering_pair_store_free(lpair, interp_mode);
- change = true;
+ changed = true;
}
BLI_assert(bm_verts_tag_count(bm) == 0);
@@ -1229,7 +1229,7 @@ cleanup:
BM_mesh_edgeloops_free(&eloops_rim);
/* flag output */
- if (change) {
+ if (changed) {
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
}
}
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 1a1201c015e..26d02cfc084 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -294,11 +294,22 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const
/* -------------------------------------------------------------------- */
/* Update the edge cost of rotation in the heap */
+BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const int edge_array_len)
+{
+ const int index = BM_elem_index_get(e);
+ return ((index >= 0) &&
+ (index < edge_array_len) &&
+ (e == edge_array[index]));
+}
+
/* recalc an edge in the heap (surrounding geometry has changed) */
static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ /* only for testing the edge is in the array */
+ const BMEdge **edge_array, const int edge_array_len,
+
const short flag, const short method)
{
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ if (edge_in_array(e, edge_array, edge_array_len)) {
const int i = BM_elem_index_get(e);
GSet *e_state_set = edge_state_arr[i];
@@ -309,8 +320,6 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
/* check if we can add it back */
BLI_assert(BM_edge_is_manifold(e) == true);
- //BLI_assert(BMO_elem_flag_test(bm, e->l->f, FACE_MARK) &&
- // BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK));
/* check we're not moving back into a state we have been in before */
if (e_state_set != NULL) {
@@ -337,29 +346,38 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
/* we have rotated an edge, tag other edges and clear this one */
static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ const BMEdge **edge_array, const int edge_array_len,
+ /* only for testing the edge is in the array */
const short flag, const short method)
{
- BMLoop *l;
+ int i;
+
+ BMEdge *e_arr[4] = {
+ e->l->next->e,
+ e->l->prev->e,
+ e->l->radial_next->next->e,
+ e->l->radial_next->prev->e,
+ };
+
BLI_assert(e->l->f->len == 3 &&
e->l->radial_next->f->len == 3);
- l = e->l;
- bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag, method);
- bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag, method);
- l = l->radial_next;
- bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag, method);
- bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag, method);
+ BLI_assert(BM_edge_face_count(e) == 2);
+
+ for (i = 0; i < 4; i++) {
+ bm_edge_update_beauty_cost_single(
+ e_arr[i],
+ eheap, eheap_table, edge_state_arr,
+ edge_array, edge_array_len,
+ flag, method);
+ }
}
/* -------------------------------------------------------------------- */
/* Beautify Fill */
-#define ELE_NEW 1
-#define FACE_MARK 2
-
/**
- * \note All edges in \a edge_array must be tagged and
- * have their index values set according to their position in the array.
+ * \note This function sets the edge indicies to invalid values.
*/
void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
const short flag, const short method,
@@ -389,14 +407,22 @@ void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_
else {
eheap_table[i] = NULL;
}
+
+ BM_elem_index_set(e, i); /* set_dirty */
}
+ bm->elem_index_dirty |= BM_EDGE;
while (BLI_heap_is_empty(eheap) == false) {
BMEdge *e = BLI_heap_popmin(eheap);
i = BM_elem_index_get(e);
eheap_table[i] = NULL;
+ BLI_assert(BM_edge_face_count(e) == 2);
+
e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
+
+ BLI_assert(e == NULL || BM_edge_face_count(e) == 2);
+
if (LIKELY(e)) {
GSet *e_state_set = edge_state_arr[i];
@@ -419,7 +445,9 @@ void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_
BM_elem_index_set(e, i);
/* recalculate faces connected on the heap */
- bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr, flag, method);
+ bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr,
+ (const BMEdge **)edge_array, edge_array_len,
+ flag, method);
/* update flags */
if (oflag_edge)
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 5e68e468fb8..7f39cbee2c5 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -35,6 +35,7 @@
#include "BLI_array.h"
#include "BLI_alloca.h"
+#include "BLI_gsqueue.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
@@ -75,6 +76,8 @@ typedef struct EdgeHalf {
int seg; /* how many segments for the bevel */
float offset_l; /* offset for this edge, on left side */
float offset_r; /* offset for this edge, on right side */
+ float offset_l_spec; /* user specification for offset_l */
+ float offset_r_spec; /* user specification for offset_r */
bool is_bev; /* is this edge beveled? */
bool is_rev; /* is e->v2 the vertex at this end? */
bool is_seam; /* is e a seam for custom loopdata (e.g., UVs)? */
@@ -117,6 +120,7 @@ typedef struct BevVert {
int selcount; /* number of selected edges around the vertex */
float offset; /* offset for this vertex, if vertex_only bevel */
bool any_seam; /* any seams on attached edges? */
+ bool visited; /* used in graph traversal */
EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
VMesh *vmesh; /* mesh structure for replacing vertex */
} BevVert;
@@ -134,6 +138,7 @@ typedef struct BevelParams {
bool vertex_only; /* bevel vertices only */
bool use_weights; /* bevel amount affected by weights on edges or verts */
bool preserve_widths; /* should bevel prefer widths over angles, if forced to choose? */
+ bool limit_offset; /* should offsets be limited by collisions? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
} BevelParams;
@@ -166,6 +171,11 @@ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float
return ans;
}
+BLI_INLINE void adjust_bound_vert(BoundVert *bv, const float co[3])
+{
+ copy_v3_v3(bv->nv.co, co);
+}
+
/* Mesh verts are indexed (i, j, k) where
* i = boundvert index (0 <= i < nv)
* j = ring index (0 <= j <= ns2)
@@ -216,21 +226,55 @@ static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
}
/* Find the EdgeHalf representing the other end of e->e.
+ * Return other end's BevVert in *bvother, if r_bvother is provided.
* That may not have been constructed yet, in which case return NULL. */
-static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e)
+static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert **r_bvother)
{
- BevVert *bvother;
+ BevVert *bvo;
EdgeHalf *eother;
- bvother = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
- if (bvother) {
- eother = find_edge_half(bvother, e->e);
+ bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
+ if (bvo) {
+ if (r_bvother)
+ *r_bvother = bvo;
+ eother = find_edge_half(bvo, e->e);
BLI_assert(eother != NULL);
return eother;
}
+ else if (r_bvother) {
+ *r_bvother = NULL;
+ }
return NULL;
}
+static bool other_edge_half_visited(BevelParams *bp, EdgeHalf *e)
+{
+ BevVert *bvo;
+
+ bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
+ if (bvo)
+ return bvo->visited;
+ else
+ return false;
+}
+
+static bool edge_half_offset_changed(EdgeHalf *e)
+{
+ return e->offset_l != e->offset_l_spec ||
+ e->offset_r != e->offset_r_spec;
+}
+
+static bool any_edge_half_offset_changed(BevVert *bv)
+{
+ int i;
+
+ for (i = 0; i < bv->edgecount; i++) {
+ if (edge_half_offset_changed(&bv->edges[i]))
+ return true;
+ }
+ return false;
+}
+
/* Return the next EdgeHalf after from_e that is beveled.
* If from_e is NULL, find the first beveled edge. */
static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
@@ -472,11 +516,14 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
* When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
* but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
* lead to different offsets) then meeting point can be found be intersecting offset lines.
+ * If making the meeting point significantly changes the left or right offset from the user spec,
+ * record the change in offset_l (or offset_r); later we can tell that a change has happened because
+ * the offset will differ from its original value in offset_l_spec (or offset_r_spec).
*/
static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float meetco[3])
{
float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
- off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang;
+ off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang, d;
/* get direction vectors for two offset lines */
sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
@@ -495,13 +542,17 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
normalize_v3(norm_perp1);
copy_v3_v3(off1a, v->co);
madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
+ if (e2->offset_l != e1->offset_r)
+ e2->offset_l = e1->offset_r;
copy_v3_v3(meetco, off1a);
}
else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) {
/* special case e1 and e2 are antiparallel, so bevel is into
* a zero-area face. Just make the offset point on the
* common line, at offset distance from v. */
- slide_dist(e2, v, e2->offset_l, meetco);
+ slide_dist(e2, v, e1->offset_r, meetco);
+ if (e2->offset_l != e1->offset_r)
+ e2->offset_l = e1->offset_r;
}
else {
/* Get normal to plane where meet point should be,
@@ -532,45 +583,122 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float
BLI_assert(!"offset_meet failure");
#endif
copy_v3_v3(meetco, off1a); /* just to do something */
+ d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+ if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
+ e2->offset_l = d;
}
}
}
-/* Like offset_in_two planes, but for the case where we prefer to solve the problem
- * of not meeting at the same point by choosing to change the bevel offset on one
- * of the appropriate side of either e1 or e2, in order that the lines can meet on emid. */
+/* Calculate the meeting point between e1 and e2 (one of which should have zero offsets),
+ * where e1 precedes e2 in CCW order around their common vertex v (viewed from normal side).
+ * If r_angle is provided, return the angle between e and emeet in *r_angle.
+ * If the angle is 0, or it is 180 degrees or larger, there will be no meeting point;
+ * return false in that case, else true */
+static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetco[3], float *r_angle)
+{
+ float dir1[3], dir2[3], fno[3], ang, sinang;
+
+ sub_v3_v3v3(dir1, BM_edge_other_vert(e1->e, v)->co, v->co);
+ sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+
+ /* find angle from dir1 to dir2 as viewed from vertex normal side */
+ ang = angle_normalized_v3v3(dir1, dir2);
+ if (ang < BEVEL_EPSILON) {
+ if (r_angle)
+ *r_angle = 0.0f;
+ return false;
+ }
+ cross_v3_v3v3(fno, dir1, dir2);
+ if (dot_v3v3(fno, v->no) < 0.0f)
+ ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
+ if (r_angle)
+ *r_angle = ang;
+
+ if (ang - (float)M_PI > BEVEL_EPSILON)
+ return false;
+
+ sinang = sinf(ang);
+ copy_v3_v3(meetco, v->co);
+ if (e1->offset_r == 0.0f)
+ madd_v3_v3fl(meetco, dir1, e2->offset_l / sinang);
+ else
+ madd_v3_v3fl(meetco, dir2, e1->offset_r / sinang);
+ return true;
+}
+
+/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
+ * on the in-between edge emid. Viewed from the vertex normal side, the CCW
+ * order of these edges is e1, emid, e2.
+ * The offsets probably do not meet at a common point on emid, so need to pick
+ * one that causes the least problems. If the other end of one of e1 or e2 has been visited
+ * already, prefer to keep the offset the same on this end.
+ * Otherwise, pick a point between the two intersection points on emid that minimizes
+ * the sum of squares of errors from desired offset. */
static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
BMVert *v, float meetco[3])
{
+ float d, ang1, ang2, sina1, sina2, lambda;
+ float meet1[3], meet2[3];
+ bool visited1, visited2, ok1, ok2;
+
BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
-
- /* If have to change offset of e1 or e2, which one?
- * Prefer the one whose other end hasn't been constructed yet.
- * Following will choose to change e2 if both have already been constructed. */
- if (find_other_end_edge_half(bp, e1)) {
- offset_meet(e1, emid, v, e1->fnext, meetco);
- /* now e2's left offset is probably different */
- e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+
+ visited1 = other_edge_half_visited(bp, e1);
+ visited2 = other_edge_half_visited(bp, e2);
+
+ ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
+ ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
+ if (ok1 && ok2) {
+ if (visited1 && !visited2) {
+ copy_v3_v3(meetco, meet1);
+ }
+ else if (!visited1 && visited2) {
+ copy_v3_v3(meetco, meet2);
+ }
+ else {
+ /* find best compromise meet point */
+ sina1 = sinf(ang1);
+ sina2 = sinf(ang2);
+ lambda = sina2 * sina2 / (sina1 * sina1 + sina2 * sina2);
+ interp_v3_v3v3(meetco, meet1, meet2, lambda);
+ }
}
- else {
- offset_meet(emid, e2, v, emid->fnext, meetco);
- /* now e1's right offset is probably different */
- e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
+ else if (ok1 && !ok2) {
+ copy_v3_v3(meetco, meet1);
+ }
+ else if (!ok1 && ok2) {
+ copy_v3_v3(meetco, meet2);
}
+ else {
+ /* Neither offset line met emid.
+ * This should only happen if all three lines are on top of each other */
+ slide_dist(emid, v, e1->offset_r, meetco);
+ }
+
+ /* offsets may have changed now */
+ d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
+ if (fabsf(d - e1->offset_r) > BEVEL_EPSILON)
+ e1->offset_r = d;
+ d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+ if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
+ e2->offset_l = d;
}
-/* Like offset_meet, but with a mid edge between them that is used
- * to calculate the planes in which to run the offset lines.
- * They may not meet exactly: the lines may be angled so that they can't meet,
- * probably because one or both faces is non-planar.
- * In that case, pick a close point on emid, which should be the dividing
- * edge between the two planes. */
+/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
+ * when there is an in-between edge emid, and we prefer to have a point that may not
+ * be on emid if that does a better job of keeping offsets at the user spec.
+ * Viewed from the vertex normal side, the CCW order of the edges is e1, emid, e2.
+ * The offset lines may not meet exactly: the lines may be angled so that they can't meet.
+ * In that case, pick the the offset_on_edge_between. */
static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3])
+ BMVert *v, float meetco[3])
{
float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3],
off1a[3], off1b[3], off2a[3], off2b[3], isect2[3],
- f1no[3], f2no[3], ang;
+ f1no[3], f2no[3], ang, d;
int iret;
/* get direction vectors for two offset lines */
@@ -610,17 +738,23 @@ static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, Ed
}
else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) {
slide_dist(e2, v, e2->offset_l, meetco);
+ d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
+ if (fabsf(d - e1->offset_r) > BEVEL_EPSILON)
+ e1->offset_r = d;
}
else {
iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
if (iret == 0) {
/* lines colinear: another test says they are parallel. so shouldn't happen */
copy_v3_v3(meetco, off1a);
+ d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
+ if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
+ e2->offset_l = d;
}
else if (iret == 2) {
/* lines are not coplanar and don't meet; meetco and isect2 are nearest to first and second lines */
if (len_v3v3(meetco, isect2) > 100.0f * BEVEL_EPSILON) {
- /* offset lines don't meet so can't preserve widths; fallback on sliding along edge between */
+ /* offset lines don't meet so can't preserve widths */
offset_on_edge_between(bp, e1, e2, emid, v, meetco);
}
}
@@ -645,7 +779,7 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, floa
}
else {
zero_v3(no);
- if (fabs(dir[0]) < fabs(dir[1]))
+ if (fabsf(dir[0]) < fabsf(dir[1]))
no[0] = 1.0f;
else
no[1] = 1.0f;
@@ -828,13 +962,22 @@ static void set_bound_vert_seams(BevVert *bv)
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
* of a vertex on the the boundary of the beveled vertex bv->v.
- * Also decide on the mesh pattern that will be used inside the boundary.
+ * This may adjust some EdgeHalf widths, and there might have to be
+ * a subsequent pass to make the widths as consistent as possible.
+ * The first time through, construct will be true and we are making the BoundVerts
+ * and setting up the BoundVert and EdgeHalf pointers appropriately.
+ * For a width consistency path, we just recalculate the coordinates of the
+ * BoundVerts. If the other ends have been (re)built already, then we
+ * copy the offsets from there to match, else we use the ideal (user-specified)
+ * widths.
+ * Also, if construct, decide on the mesh pattern that will be used inside the boundary.
* Doesn't make the actual BMVerts */
-static void build_boundary(BevelParams *bp, BevVert *bv)
+static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e;
+ EdgeHalf *efirst, *e, *eother;
BoundVert *v;
+ BevVert *bvother;
VMesh *vm;
float co[3];
const float *no;
@@ -842,10 +985,26 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
vm = bv->vmesh;
- if (bp->vertex_only)
+ if (bp->vertex_only) {
e = efirst = &bv->edges[0];
- else
+ }
+ else {
e = efirst = next_bev(bv, NULL);
+ do {
+ eother = find_other_end_edge_half(bp, e, &bvother);
+ if (eother && bvother->visited && bp->offset_type != BEVEL_AMT_PERCENT) {
+ /* try to keep bevel even by matching other end offsets */
+ e->offset_l = eother->offset_r;
+ e->offset_r = eother->offset_l;
+ }
+ else {
+ /* reset to user spec */
+ e->offset_l = e->offset_l_spec;
+ e->offset_r = e->offset_r_spec;
+ }
+ } while ((e = e->next) != efirst);
+ e = efirst;
+ }
BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */
@@ -853,38 +1012,58 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
/* special case: beveled edge meets non-beveled one at valence 2 vert */
no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
offset_in_plane(e, no, TRUE, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = v->ebev = e;
- e->leftv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = v->ebev = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
offset_in_plane(e, no, FALSE, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e;
- e->rightv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
/* make artifical extra point along unbeveled edge, and form triangle */
slide_dist(e->next, bv->v, e->offset_l, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e->next;
- e->next->leftv = e->next->rightv = v;
- /* could use M_POLY too, but tri-fan looks nicer)*/
- vm->mesh_kind = M_TRI_FAN;
- set_bound_vert_seams(bv);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e->next;
+ e->next->leftv = e->next->rightv = v;
+ /* could use M_POLY too, but tri-fan looks nicer)*/
+ vm->mesh_kind = M_TRI_FAN;
+ set_bound_vert_seams(bv);
+ }
+ else {
+ adjust_bound_vert(e->next->leftv, co);
+ }
return;
}
lastd = bp->vertex_only ? bv->offset : e->offset_l;
- vm->boundstart = NULL;
do {
if (e->is_bev) {
/* handle only left side of beveled edge e here: next iteration should do right side */
if (e->prev->is_bev) {
BLI_assert(e->prev != e); /* see: wire edge special case */
offset_meet(e->prev, e, bv->v, e->fprev, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev;
- v->elast = v->ebev = e;
- e->leftv = v;
- e->prev->rightv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ v = e->leftv;
+ adjust_bound_vert(v, co);
+ }
}
else {
/* e->prev is not beveled */
@@ -895,21 +1074,33 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
offset_in_two_planes(bp, e->prev->prev, e, e->prev, bv->v, co);
else
offset_on_edge_between(bp, e->prev->prev, e, e->prev, bv->v, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev->prev;
- v->elast = v->ebev = e;
- e->leftv = v;
- e->prev->leftv = v;
- e->prev->prev->rightv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = v;
+ e->prev->prev->rightv = v;
+ }
+ else {
+ v = e->leftv;
+ adjust_bound_vert(v, co);
+ }
}
else {
/* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */
offset_meet(e->prev, e, bv->v, e->fprev, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev;
- v->elast = v->ebev = e;
- e->leftv = v;
- e->prev->leftv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = v;
+ }
+ else {
+ v = e->leftv;
+ adjust_bound_vert(v, co);
+ }
}
}
lastd = len_v3v3(bv->v->co, v->nv.co);
@@ -923,11 +1114,16 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
else if (e->prev->is_bev) {
/* on-edge meet between e->prev and e */
offset_meet(e->prev, e, bv->v, e->fprev, co);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev;
- v->elast = e;
- e->leftv = v;
- e->prev->rightv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = e;
+ e->leftv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
}
else {
/* None of e->prev, e, e->next are beveled.
@@ -936,41 +1132,124 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
* 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);
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e;
- e->leftv = v;
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
}
}
} while ((e = e->next) != efirst);
- set_bound_vert_seams(bv);
+ if (construct) {
+ set_bound_vert_seams(bv);
- BLI_assert(vm->count >= 2);
- if (bp->vertex_only) {
- if (vm->count == 2)
+ BLI_assert(vm->count >= 2);
+ if (bp->vertex_only) {
+ if (vm->count == 2)
+ vm->mesh_kind = M_NONE;
+ else if (bp->seg > 1)
+ vm->mesh_kind = M_ADJ_SUBDIV;
+ else
+ vm->mesh_kind = M_POLY;
+ }
+ else if (vm->count == 2 && bv->edgecount == 3) {
vm->mesh_kind = M_NONE;
- else if (bp->seg > 1)
- vm->mesh_kind = M_ADJ_SUBDIV;
- else
- vm->mesh_kind = M_POLY;
- }
- else if (vm->count == 2 && bv->edgecount == 3) {
- vm->mesh_kind = M_NONE;
- }
- else if (bv->selcount == 2) {
- vm->mesh_kind = M_QUAD_STRIP;
- }
- else if (efirst->seg == 1 || bv->selcount == 1) {
- if (vm->count == 3 && bv->selcount == 1) {
- vm->mesh_kind = M_TRI_FAN;
+ }
+ else if (bv->selcount == 2) {
+ vm->mesh_kind = M_QUAD_STRIP;
+ }
+ else if (efirst->seg == 1 || bv->selcount == 1) {
+ if (vm->count == 3 && bv->selcount == 1) {
+ vm->mesh_kind = M_TRI_FAN;
+ }
+ else {
+ vm->mesh_kind = M_POLY;
+ }
}
else {
- vm->mesh_kind = M_POLY;
+ vm->mesh_kind = M_ADJ;
}
}
- else {
- vm->mesh_kind = M_ADJ;
+}
+
+/* Do a global pass to try to make offsets as even as possible.
+ * Consider this graph:
+ * nodes = BevVerts
+ * edges = { (u,v) } where u and v are nodes such that u and v
+ * are connected by a mesh edge that has at least one end
+ * whose offset does not match the user spec.
+ *
+ * Do a breadth-first search on this graph, starting from nodes
+ * that have any_adjust=true, and changing all
+ * not-already-changed offsets on EdgeHalfs to match the
+ * corresponding ones that changed on the other end.
+ * The graph is dynamic in the sense that having an offset that
+ * doesn't meet the user spec can be added as the search proceeds.
+ * We want this search to be deterministic (not dependendent
+ * on order of processing through hash table), so as to avoid
+ * flicker to to different decisions made if search is different
+ * while dragging the offset number in the UI. So look for the
+ * lower vertex number when there is a choice of where to start.
+ *
+ * Note that this might not process all BevVerts, only the ones
+ * that need adjustment.
+ */
+static void adjust_offsets(BevelParams *bp)
+{
+ BevVert *bv, *searchbv, *bvother;
+ int i, searchi;
+ GHashIterator giter;
+ EdgeHalf *e, *efirst, *eother;
+ GSQueue *q;
+
+ BLI_assert(!bp->vertex_only);
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ bv->visited = false;
+ }
+
+ q = BLI_gsqueue_new((int)sizeof(BevVert *));
+ /* the following loop terminates because at least one node is visited each time */
+ for (;;) {
+ /* look for root of a connected component in search graph */
+ searchbv = NULL;
+ searchi = -1;
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ if (!bv->visited && any_edge_half_offset_changed(bv)) {
+ i = BM_elem_index_get(bv->v);
+ if (!searchbv || i < searchi) {
+ searchbv = bv;
+ searchi = i;
+ }
+ }
+ }
+ if (searchbv == NULL)
+ break;
+
+ BLI_gsqueue_push(q, &searchbv);
+ while (!BLI_gsqueue_is_empty(q)) {
+ BLI_gsqueue_pop(q, &bv);
+ /* If do this check, don't have to check for already-on-queue before push, below */
+ if (bv->visited)
+ continue;
+ bv->visited = true;
+ build_boundary(bp, bv, false);
+
+ e = efirst = &bv->edges[0];
+ do {
+ eother = find_other_end_edge_half(bp, e, &bvother);
+ if (eother && !bvother->visited && edge_half_offset_changed(e)) {
+ BLI_gsqueue_push(q, &bvother);
+ }
+ } while ((e = e->next) != efirst);
+ }
}
+ BLI_gsqueue_free(q);
}
/*
@@ -1989,14 +2268,15 @@ static float edge_face_angle(EdgeHalf *e)
/*
* Construction around the vertex
*/
-static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
+static BevVert * bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
BMEdge *bme;
BevVert *bv;
BMEdge *bme2, *unflagged_bme, *first_bme;
BMFace *f;
+ BMVert *v1, *v2;
BMIter iter, iter2;
- EdgeHalf *e, *eother;
+ EdgeHalf *e;
float weight, z;
int i, found_shared_face, ccw_test_sum;
int nsel = 0;
@@ -2034,7 +2314,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
if ((nsel == 0 && !bp->vertex_only) || (ntot < 2 && bp->vertex_only)) {
/* signal this vert isn't being beveled */
BM_elem_flag_disable(v, BM_ELEM_TAG);
- return;
+ return NULL;
}
/* avoid calling BM_vert_edge_count since we loop over edges already */
@@ -2049,7 +2329,6 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf));
bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh));
bv->vmesh->seg = bp->seg;
- BLI_ghash_insert(bp->vert_hash, v, bv);
if (bp->vertex_only) {
/* if weighted, modify offset by weight */
@@ -2057,11 +2336,12 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
weight = defvert_find_weight(bp->dvert + BM_elem_index_get(v), bp->vertex_group);
if (weight <= 0.0f) {
BM_elem_flag_disable(v, BM_ELEM_TAG);
- return;
+ return NULL;
}
bv->offset *= weight;
}
}
+ BLI_ghash_insert(bp->vert_hash, v, bv);
/* add edges to bv->edges in order that keeps adjacent edges sharing
* a face, if possible */
@@ -2153,57 +2433,55 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
if (e->is_bev) {
/* Convert distance as specified by user into offsets along
* faces on left side and right side of this edgehalf.
- * Except for percent method, offset will be same on each side.
- *
- * First check to see if other end has had construction made,
- * because offset may have been forced to another number
- * (but for percent method all 4 widths can be different). */
-
- eother = find_other_end_edge_half(bp, e);
- if (eother && bp->offset_type != BEVEL_AMT_PERCENT) {
- e->offset_l = eother->offset_r;
- e->offset_r = eother->offset_l;
+ * Except for percent method, offset will be same on each side. */
+
+ switch (bp->offset_type) {
+ case BEVEL_AMT_OFFSET:
+ e->offset_l_spec = bp->offset;
+ break;
+ case BEVEL_AMT_WIDTH:
+ z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
+ if (z < BEVEL_EPSILON)
+ e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ else
+ e->offset_l_spec = bp->offset / z;
+ break;
+ case BEVEL_AMT_DEPTH:
+ z = fabsf(cosf(edge_face_angle(e) / 2.0f));
+ if (z < BEVEL_EPSILON)
+ e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ else
+ e->offset_l_spec = bp->offset / z;
+ break;
+ case BEVEL_AMT_PERCENT:
+ /* offset needs to be such that it meets adjacent edges at percentage of their lengths */
+ v1 = BM_edge_other_vert(e->prev->e, v);
+ v2 = BM_edge_other_vert(e->e, v);
+ z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset * z / 100.0f;
+ v1 = BM_edge_other_vert(e->e, v);
+ v2 = BM_edge_other_vert(e->next->e, v);
+ z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset * z / 100.0f;
+ break;
+ default:
+ BLI_assert(!"bad bevel offset kind");
+ e->offset_l_spec = bp->offset;
+ break;
}
- else {
- switch (bp->offset_type) {
- case BEVEL_AMT_OFFSET:
- e->offset_l = bp->offset;
- break;
- case BEVEL_AMT_WIDTH:
- z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
- if (z < BEVEL_EPSILON)
- e->offset_l = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
- else
- e->offset_l = bp->offset / z;
- break;
- case BEVEL_AMT_DEPTH:
- z = fabsf(cosf(edge_face_angle(e) / 2.0f));
- if (z < BEVEL_EPSILON)
- e->offset_l = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
- else
- e->offset_l = bp->offset / z;
- break;
- case BEVEL_AMT_PERCENT:
- e->offset_l = BM_edge_calc_length(e->prev->e) * bp->offset / 100.0f;
- e->offset_r = BM_edge_calc_length(e->next->e) * bp->offset / 100.0f;
- break;
- default:
- BLI_assert(!"bad bevel offset kind");
- e->offset_l = bp->offset;
- break;
- }
- if (bp->offset_type != BEVEL_AMT_PERCENT)
- e->offset_r = e->offset_l;
- if (bp->use_weights) {
- weight = BM_elem_float_data_get(&bm->edata, e->e, CD_BWEIGHT);
- e->offset_l *= weight;
- e->offset_r *= weight;
- }
+ if (bp->offset_type != BEVEL_AMT_PERCENT)
+ e->offset_r_spec = e->offset_l_spec;
+ if (bp->use_weights) {
+ weight = BM_elem_float_data_get(&bm->edata, e->e, CD_BWEIGHT);
+ e->offset_l_spec *= weight;
+ e->offset_r_spec *= weight;
}
}
else {
- e->offset_l = e->offset_r = 0.0f;
+ e->offset_l_spec = e->offset_r_spec = 0.0f;
}
+ e->offset_l = e->offset_l_spec;
+ e->offset_r = e->offset_r_spec;
BM_BEVEL_EDGE_TAG_DISABLE(e->e);
if (e->fprev && e->fnext)
@@ -2212,8 +2490,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->is_seam = true;
}
- build_boundary(bp, bv);
- build_vmesh(bp, bm, bv);
+ return bv;
}
/* Face f has at least one beveled vertex. Rebuild f */
@@ -2484,6 +2761,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const f
BMIter iter;
BMVert *v, *v_next;
BMEdge *e;
+ BevVert *bv;
BevelParams bp = {NULL};
bp.offset = offset;
@@ -2492,6 +2770,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const f
bp.vertex_only = vertex_only;
bp.use_weights = use_weights;
bp.preserve_widths = false;
+ bp.limit_offset = limit_offset;
bp.dvert = dvert;
bp.vertex_group = vertex_group;
@@ -2504,10 +2783,26 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const f
if (limit_offset)
bp.offset = bevel_limit_offset(bm, &bp);
- /* Analyze input vertices and build vertex meshes */
+ /* Analyze input vertices, sorting edges and assigning initial new vertex positions */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = bevel_vert_construct(bm, &bp, v);
+ if (bv)
+ build_boundary(&bp, bv, true);
+ }
+ }
+
+ /* Perhaps do a pass to try to even out widths */
+ if (!bp.vertex_only) {
+ adjust_offsets(&bp);
+ }
+
+ /* Build the meshes around vertices, now that positions are final */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bevel_vert_construct(bm, &bp, v);
+ bv = find_bevvert(&bp, v);
+ if (bv)
+ build_vmesh(&bp, bm, bv);
}
}
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 99d46559ca5..3ee238ad54f 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -250,6 +250,9 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
}
// print("COST %.12f\n");
+ /* note, 'cost' shouldn't be negative but happens sometimes with small values.
+ * this can cause faces that make up a flat surface to over-collapse, see [#37121] */
+ cost = fabsf(cost);
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e);
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 59c2aa4331d..446c03a543f 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -47,13 +47,13 @@ static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_ar
const bool use_tag,
BMOperator *op, BMOpSlot *slot_facemap_out)
{
- const int faces_array_tot = face->len - 3;
+ 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, sf_arena, quad_method, ngon_method, use_tag);
+ BM_face_triangulate(bm, face, faces_array, &faces_array_tot, sf_arena, quad_method, ngon_method, use_tag);
- if (faces_array) {
+ if (faces_array_tot) {
int i;
BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
for (i = 0; i < faces_array_tot; i++) {
@@ -87,7 +87,7 @@ 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, sf_arena, quad_method, ngon_method, tag_only);
+ BM_face_triangulate(bm, face, NULL, NULL, sf_arena, quad_method, ngon_method, tag_only);
}
}
}
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 79c725166f6..144fe75fa70 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -1127,6 +1127,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
et->setData("energy", &(lamp->energy));
et->setData("dist", &(lamp->dist));
et->setData("spotsize", &(lamp->spotsize));
+ lamp->spotsize = DEG2RADF(lamp->spotsize);
et->setData("spotblend", &(lamp->spotblend));
et->setData("halo_intensity", &(lamp->haint));
et->setData("att1", &(lamp->att1));
@@ -1134,7 +1135,6 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
et->setData("falloff_type", &(lamp->falloff_type));
et->setData("clipsta", &(lamp->clipsta));
et->setData("clipend", &(lamp->clipend));
- et->setData("shadspotsize", &(lamp->shadspotsize));
et->setData("bias", &(lamp->bias));
et->setData("soft", &(lamp->soft));
et->setData("compressthresh", &(lamp->compressthresh));
@@ -1224,7 +1224,7 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
lamp->falloff_type = LA_FALLOFF_INVSQUARE;
if (IS_EQ(att2, 0.0f) && att1 > 0)
lamp->falloff_type = LA_FALLOFF_INVLINEAR;
- lamp->spotsize = light->getFallOffAngle().getValue();
+ lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue());
lamp->spotblend = light->getFallOffExponent().getValue();
}
break;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 4c17b8871f5..d848db671a1 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -357,9 +357,9 @@ void GeometryExporter::createPolylist(short material_index,
// char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(makeTexcoordSourceId(geom_id, i)),
- 2, // offset always 2, this is only until we have optimized UV sets
- i // set number equals UV map index
+ makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
);
til.push_back(input3);
}
@@ -474,10 +474,15 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
}
-std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index)
+std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index, bool is_single_layer)
{
char suffix[20];
- sprintf(suffix, "-%d", layer_index);
+ if (is_single_layer) {
+ suffix[0] = '\0';
+ }
+ else {
+ sprintf(suffix, "-%d", layer_index);
+ }
return getIdBySemantics(geom_id, COLLADASW::InputSemantic::TEXCOORD) + suffix;
}
@@ -493,7 +498,6 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
// write <source> for each layer
// each <source> will get id like meshName + "map-channel-1"
- int map_index = 0;
int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
for (int a = 0; a < num_layers; a++) {
@@ -501,7 +505,7 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string layer_id = makeTexcoordSourceId(geom_id, map_index++);
+ std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 3719072fe0c..5b67f80e98d 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -88,7 +88,7 @@ public:
void createVertexColorSource(std::string geom_id, Mesh *me);
- std::string makeTexcoordSourceId(std::string& geom_id, int layer_index);
+ std::string makeTexcoordSourceId(std::string& geom_id, int layer_index, bool is_single_layer);
//creates <source> for texcoords
void createTexcoordsSource(std::string geom_id, Mesh *me);
diff --git a/source/blender/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp
index af13d61a368..ff50abfedae 100644
--- a/source/blender/collada/LightExporter.cpp
+++ b/source/blender/collada/LightExporter.cpp
@@ -101,7 +101,7 @@ void LightsExporter::operator()(Object *ob)
else if (la->type == LA_SPOT) {
COLLADASW::SpotLight cla(mSW, la_id, la_name);
cla.setColor(col, false, "color");
- cla.setFallOffAngle(la->spotsize, false, "fall_off_angle");
+ cla.setFallOffAngle(RAD2DEGF(la->spotsize), false, "fall_off_angle");
cla.setFallOffExponent(la->spotblend, false, "fall_off_exponent");
cla.setConstantAttenuation(constatt);
cla.setLinearAttenuation(linatt);
@@ -147,7 +147,7 @@ bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Lamp *la)
cla.addExtraTechniqueParameter("blender", "shadow_b", la->shdwb, "blender_shadow_b");
cla.addExtraTechniqueParameter("blender", "energy", la->energy, "blender_energy");
cla.addExtraTechniqueParameter("blender", "dist", la->dist, "blender_dist");
- cla.addExtraTechniqueParameter("blender", "spotsize", la->spotsize);
+ cla.addExtraTechniqueParameter("blender", "spotsize", RAD2DEGF(la->spotsize));
cla.addExtraTechniqueParameter("blender", "spotblend", la->spotblend);
cla.addExtraTechniqueParameter("blender", "halo_intensity", la->haint, "blnder_halo_intensity");
cla.addExtraTechniqueParameter("blender", "att1", la->att1);
@@ -156,7 +156,6 @@ bool LightsExporter::exportBlenderProfile(COLLADASW::Light &cla, Lamp *la)
cla.addExtraTechniqueParameter("blender", "falloff_type", la->falloff_type);
cla.addExtraTechniqueParameter("blender", "clipsta", la->clipsta);
cla.addExtraTechniqueParameter("blender", "clipend", la->clipend);
- cla.addExtraTechniqueParameter("blender", "shadspotsize", la->shadspotsize);
cla.addExtraTechniqueParameter("blender", "bias", la->bias);
cla.addExtraTechniqueParameter("blender", "soft", la->soft);
cla.addExtraTechniqueParameter("blender", "compressthresh", la->compressthresh);
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index f10e6696c6a..7d8511540f7 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -214,136 +214,109 @@ static const float EWA_WTS[EWA_MAXIDX + 1] = {
0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
};
-static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F)
+static void ellipse_bounds(float A, float B, float C, float F, float &xmax, float &ymax)
{
- float ct2 = cosf(th);
- const float st2 = 1.f - ct2 * ct2; // <- sin(th)^2
- ct2 *= ct2;
- *A = a2 * st2 + b2 * ct2;
- *B = (b2 - a2) * sinf(2.f * th);
- *C = a2 * ct2 + b2 * st2;
- *F = a2 * b2;
-}
-
-// all tests here are done to make sure possible overflows are hopefully minimized
-static void imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc)
-{
- if (F <= 1e-5f) { // use arbitrary major radius, zero minor, infinite eccentricity
- *a = sqrtf(A > C ? A : C);
- *b = 0.f;
- *ecc = 1e10f;
- *th = 0.5f * (atan2f(B, A - C) + (float)M_PI);
+ float denom = 4.0f * A * C - B * B;
+ if (denom > 0.0f && A != 0.0f && C != 0.0f) {
+ xmax = sqrt(F) / (2.0f * A) * (sqrt(F * (4.0f * A - B * B / C)) + B * B * sqrt(F / (C * denom)));
+ ymax = sqrt(F) / (2.0f * C) * (sqrt(F * (4.0f * C - B * B / A)) + B * B * sqrt(F / (A * denom)));
}
else {
- const float AmC = A - C, ApC = A + C, F2 = F * 2.f;
- const float r = sqrtf(AmC * AmC + B * B);
- float d = ApC - r;
- *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
- d = ApC + r;
- if (d <= 0.f) {
- *b = 0.f;
- *ecc = 1e10f;
- }
- else {
- *b = sqrtf(F2 / d);
- *ecc = *a / *b;
- }
- /* incr theta by 0.5 * pi (angle of major axis) */
- *th = 0.5f * (atan2f(B, AmC) + (float)M_PI);
+ xmax = 0.0f;
+ ymax = 0.0f;
}
}
-static float clipuv(float x, float limit)
+static void ellipse_params(float Ux, float Uy, float Vx, float Vy,
+ float &A, float &B, float &C, float &F, float &umax, float &vmax)
{
- x = (x < 0) ? 0 : ((x >= limit) ? (limit - 1) : x);
- return x;
+ A = Vx * Vx + Vy * Vy;
+ B = -2.0f * (Ux * Vx + Uy * Vy);
+ C = Ux * Ux + Uy * Uy;
+ F = A * C - B * B * 0.25f;
+
+ float factor = (F != 0.0f ? (float)(EWA_MAXIDX + 1) / F : 0.0f);
+ A *= factor;
+ B *= factor;
+ C *= factor;
+ F = (float)(EWA_MAXIDX + 1);
+
+ ellipse_bounds(A, B, C, sqrtf(F), umax, vmax);
}
/**
- * \note \a sampler at the moment is either 'COM_PS_NEAREST' or not, other values won't matter.
+ * Filtering method based on
+ * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter"
+ * by Ned Greene and Paul S. Heckbert (1986)
*/
-void MemoryBuffer::readEWA(float result[4], float fx, float fy, float dx, float dy, PixelSampler sampler)
+void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler)
{
- const int width = this->getWidth(), height = this->getHeight();
-
- // scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
- // scaling by aspect ratio alone does the opposite, so try something in between instead...
- const float ff2 = width, ff = sqrtf(ff2), q = height / ff;
- const float Ux = dx * ff, Vx = dx * q, Uy = dy * ff, Vy = dy * q;
- float A = Vx * Vx + Vy * Vy;
- float B = -2.f * (Ux * Vx + Uy * Vy);
- float C = Ux * Ux + Uy * Uy;
- float F = A * C - B * B * 0.25f;
- float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d;
- int u, v, u1, u2, v1, v2;
- // The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
- // so the ellipse always covers at least some texels. But since the filter is now always larger,
- // it also means that everywhere else it's also more blurry then ideally should be the case.
- // So instead here the ellipse radii are modified instead whenever either is too low.
- // Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
- // and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
- // (minimum values: const float rmin = intpol ? 1.f : 0.5f;)
-
- /* note: 0.765625f is too sharp, 1.0 will not blur with an exact pixel sample
- * useful to avoid blurring when there is no distortion */
-#if 0
- const float rmin = ((sampler != COM_PS_NEAREST) ? 1.5625f : 0.765625f) / ff2;
-#else
- const float rmin = ((sampler != COM_PS_NEAREST) ? 1.5625f : 1.0f ) / ff2;
-#endif
- imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
- if ((b2 = b * b) < rmin) {
- if ((a2 = a * a) < rmin) {
- B = 0.f;
- A = C = rmin;
- F = A * C;
- }
- else {
- b2 = rmin;
- radangle2imp(a2, b2, th, &A, &B, &C, &F);
- }
- }
+ zero_v4(result);
+ int width = this->getWidth(), height = this->getHeight();
+ if (width == 0 || height == 0)
+ return;
+
+ float u = uv[0], v = uv[1];
+ float Ux = derivatives[0][0], Vx = derivatives[1][0], Uy = derivatives[0][1], Vy = derivatives[1][1];
+ float A, B, C, F, ue, ve;
+ ellipse_params(Ux, Uy, Vx, Vy, A, B, C, F, ue, ve);
+
+ /* Note: highly eccentric ellipses can lead to large texture space areas to filter!
+ * This is limited somewhat by the EWA_WTS size in the loop, but a nicer approach
+ * could be the one found in
+ * "High Quality Elliptical Texture Filtering on GPU"
+ * by Pavlos Mavridis and Georgios Papaioannou
+ * in which the eccentricity of the ellipse is clamped.
+ */
+
+ int U0 = (int)u;
+ int V0 = (int)v;
+ /* pixel offset for interpolation */
+ float ufac = u - floor(u), vfac = v - floor(v);
+ /* filter size */
+ int u1 = (int)(u - ue);
+ int u2 = (int)(u + ue);
+ int v1 = (int)(v - ve);
+ int v2 = (int)(v + ve);
+
+ /* sane clamping to avoid unnecessarily huge loops */
+ /* note: if eccentricity gets clamped (see above),
+ * the ue/ve limits can also be lowered accordingly
+ */
+ if (U0 - u1 > EWA_MAXIDX) u1 = U0 - EWA_MAXIDX;
+ if (u2 - U0 > EWA_MAXIDX) u2 = U0 + EWA_MAXIDX;
+ if (V0 - v1 > EWA_MAXIDX) v1 = V0 - EWA_MAXIDX;
+ if (v2 - V0 > EWA_MAXIDX) v2 = V0 + EWA_MAXIDX;
+
+ float DDQ = 2.0f * A;
+ float U = u1 - U0;
+ float ac1 = A * (2.0f * U + 1.0f);
+ float ac2 = A * U * U;
+ float BU = B * U;
+
+ float sum = 0.0f;
+ for (int v = v1; v <= v2; ++v) {
+ float V = v - V0;
- ue = ff * sqrtf(C);
- ve = ff * sqrtf(A);
- d = (float)(EWA_MAXIDX + 1) / (F * ff2);
- A *= d;
- B *= d;
- C *= d;
-
- U0 = fx;
- V0 = fy;
- u1 = (int)(floorf(U0 - ue));
- u2 = (int)(ceilf(U0 + ue));
- v1 = (int)(floorf(V0 - ve));
- v2 = (int)(ceilf(V0 + ve));
- U0 -= 0.5f;
- V0 -= 0.5f;
- DDQ = 2.f * A;
- U = u1 - U0;
- ac1 = A * (2.f * U + 1.f);
- ac2 = A * U * U;
- BU = B * U;
-
- d = result[0] = result[1] = result[2] = result[3] = 0.f;
- for (v = v1; v <= v2; ++v) {
- const float V = v - V0;
float DQ = ac1 + B * V;
float Q = (C * V + BU) * V + ac2;
- for (u = u1; u <= u2; ++u) {
- if (Q < (float)(EWA_MAXIDX + 1)) {
+ for (int u = u1; u <= u2; ++u) {
+ if (Q < F) {
float tc[4];
- const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
- read(tc, clipuv(u, width), clipuv(v, height));
+ const float wt = EWA_WTS[CLAMPIS((int)Q, 0, EWA_MAXIDX)];
+ switch (sampler) {
+ case COM_PS_NEAREST: read(tc, u, v); break;
+ case COM_PS_BILINEAR: readBilinear(tc, (float)u + ufac, (float)v + vfac); break;
+ case COM_PS_BICUBIC: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; /* XXX no readBicubic method yet */
+ default: zero_v4(tc); break;
+ }
madd_v4_v4fl(result, tc, wt);
- d += wt;
+ sum += wt;
}
Q += DQ;
DQ += DDQ;
}
}
- // d should hopefully never be zero anymore
- d = 1.f / d;
- mul_v4_fl(result, d);
+ mul_v4_fl(result, (sum != 0.0f ? 1.0f / sum : 0.0f));
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 548744f6660..f9cde79c07f 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -245,7 +245,7 @@ public:
result[3] = color1[3] * mvaluex + color3[3] * valuex;
}
- void readEWA(float result[4], float fx, float fy, float dx, float dy, PixelSampler sampler);
+ void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler);
/**
* @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index fb5dfe2e9b7..c14a1973da5 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -32,6 +32,7 @@
#include "COM_ExecutionSystem.h"
#include <vector>
#include <string>
+#include <algorithm>
using namespace std;
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index 2eaeb664c67..c996ef5bbeb 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -88,7 +88,7 @@ protected:
* @param dy
* @param inputBuffers chunks that can be read by their ReadBufferOperation.
*/
- virtual void executePixelFiltered(float output[4], float x, float y, float dx, float dy, PixelSampler sampler) {}
+ virtual void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler) {}
public:
inline void readSampled(float result[4], float x, float y, PixelSampler sampler) {
@@ -97,16 +97,16 @@ public:
inline void read(float result[4], int x, int y, void *chunkData) {
executePixel(result, x, y, chunkData);
}
- inline void readFiltered(float result[4], float x, float y, float dx, float dy, PixelSampler sampler) {
+ inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler) {
executePixelFiltered(result, x, y, dx, dy, sampler);
}
virtual void *initializeTileData(rcti *rect) { return 0; }
- virtual void deinitializeTileData(rcti *rect, void *data) {
- }
-
- virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return 0; }
+ virtual void deinitializeTileData(rcti *rect, void *data) {}
+ virtual ~SocketReader() {}
+
+ virtual MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return 0; }
inline const unsigned int getWidth() const { return this->m_width; }
inline const unsigned int getHeight() const { return this->m_height; }
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 330e61e7fea..57e996fe3b2 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -77,9 +77,9 @@ static bool g_openclInitialized = false;
#define MAX_HIGHLIGHT 8
static bool g_highlightInitialized = false;
extern "C" {
-int g_highlightIndex;
-void **g_highlightedNodes;
-void **g_highlightedNodesRead;
+static int g_highlightIndex;
+static void **g_highlightedNodes;
+static void **g_highlightedNodesRead;
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
#define HIGHLIGHT(wp) \
diff --git a/source/blender/compositor/nodes/COM_DefocusNode.cpp b/source/blender/compositor/nodes/COM_DefocusNode.cpp
index b6dd0e526ae..c2bd8997525 100644
--- a/source/blender/compositor/nodes/COM_DefocusNode.cpp
+++ b/source/blender/compositor/nodes/COM_DefocusNode.cpp
@@ -85,7 +85,7 @@ void DefocusNode::convertToOperations(ExecutionSystem *graph, CompositorContext
BokehImageOperation *bokeh = new BokehImageOperation();
NodeBokehImage *bokehdata = new NodeBokehImage();
- bokehdata->angle = RAD2DEGF(data->rotation);
+ bokehdata->angle = data->rotation;
bokehdata->rounding = 0.0f;
bokehdata->flaps = data->bktype;
if (data->bktype < 3) {
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cpp b/source/blender/compositor/operations/COM_BokehImageOperation.cpp
index 82de750de72..6617fc62ab8 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.cpp
@@ -35,7 +35,7 @@ void BokehImageOperation::initExecution()
this->m_inverseRounding = 1.0f - this->m_data->rounding;
this->m_circularDistance = getWidth() / 2;
this->m_flapRad = (float)(M_PI * 2) / this->m_data->flaps;
- this->m_flapRadAdd = (this->m_data->angle / 360.0f) * (float)(M_PI * 2.0);
+ this->m_flapRadAdd = this->m_data->angle;
while (this->m_flapRadAdd < 0.0f) {
this->m_flapRadAdd += (float)(M_PI * 2.0);
}
diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
index 4dd92aec4c8..4e956905311 100644
--- a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp
@@ -38,7 +38,7 @@ void BoxMaskOperation::initExecution()
{
this->m_inputMask = this->getInputSocketReader(0);
this->m_inputValue = this->getInputSocketReader(1);
- const double rad = DEG2RAD((double)this->m_data->rotation);
+ const double rad = (double)this->m_data->rotation;
this->m_cosine = cos(rad);
this->m_sine = sin(rad);
this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight();
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
index 17692bd18ef..2842b47dd74 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
@@ -49,54 +49,92 @@ void DisplaceOperation::initExecution()
this->m_height_x4 = this->getHeight() * 4;
}
-
-/* minimum distance (in pixels) a pixel has to be displaced
- * in order to take effect */
-#define DISPLACE_EPSILON 0.01f
-
-void DisplaceOperation::executePixel(float output[4], int x, int y, void *data)
+void DisplaceOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float inVector[4];
- float inScale[4];
+ float xy[2] = { x, y };
+ float uv[2], deriv[2][2];
- float p_dx, p_dy; /* main displacement in pixel space */
- float d_dx, d_dy;
- float dxt, dyt;
- float u, v;
+ pixelTransform(xy, uv, deriv);
- this->m_inputScaleXProgram->readSampled(inScale, x, y, COM_PS_NEAREST);
- float xs = inScale[0];
- this->m_inputScaleYProgram->readSampled(inScale, x, y, COM_PS_NEAREST);
- float ys = inScale[0];
+ /* EWA filtering (without nearest it gets blurry with NO distortion) */
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+}
+bool DisplaceOperation::read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v)
+{
+ float width = m_inputVectorProgram->getWidth();
+ float height = m_inputVectorProgram->getHeight();
+ if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
+ r_u = 0.0f;
+ r_v = 0.0f;
+ return false;
+ }
+ else {
+ float col[4];
+ m_inputVectorProgram->readSampled(col, x, y, COM_PS_BILINEAR);
+ r_u = origin[0] - col[0] * xscale + 0.5f;
+ r_v = origin[1] - col[1] * yscale + 0.5f;
+ return true;
+ }
+}
+
+void DisplaceOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
+{
+ float col[4];
+ float uv[2]; /* temporary variables for derivative estimation */
+ int num;
+
+ m_inputScaleXProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
+ float xs = col[0];
+ m_inputScaleYProgram->readSampled(col, xy[0], xy[1], COM_PS_NEAREST);
+ float ys = col[0];
/* clamp x and y displacement to triple image resolution -
* to prevent hangs from huge values mistakenly plugged in eg. z buffers */
- CLAMP(xs, -this->m_width_x4, this->m_width_x4);
- CLAMP(ys, -this->m_height_x4, this->m_height_x4);
-
- this->m_inputVectorProgram->readSampled(inVector, x, y, COM_PS_NEAREST);
- p_dx = inVector[0] * xs;
- p_dy = inVector[1] * ys;
+ CLAMP(xs, -m_width_x4, m_width_x4);
+ CLAMP(ys, -m_height_x4, m_height_x4);
/* displaced pixel in uv coords, for image sampling */
- u = x - p_dx + 0.5f;
- v = y - p_dy + 0.5f;
-
- /* calc derivatives */
- this->m_inputVectorProgram->readSampled(inVector, x + 1, y, COM_PS_NEAREST);
- d_dx = inVector[0] * xs;
- this->m_inputVectorProgram->readSampled(inVector, x, y + 1, COM_PS_NEAREST);
- d_dy = inVector[1] * ys;
-
- /* clamp derivatives to minimum displacement distance in UV space */
- dxt = p_dx - d_dx;
- dyt = p_dy - d_dy;
-
- dxt = signf(dxt) * max_ff(fabsf(dxt), DISPLACE_EPSILON) / this->getWidth();
- dyt = signf(dyt) * max_ff(fabsf(dyt), DISPLACE_EPSILON) / this->getHeight();
+ read_displacement(xy[0], xy[1], xs, ys, xy, r_uv[0], r_uv[1]);
+
+ /* Estimate partial derivatives using 1-pixel offsets */
+ const float epsilon[2] = { 1.0f, 1.0f };
+
+ zero_v2(r_deriv[0]);
+ zero_v2(r_deriv[1]);
+
+ num = 0;
+ if (read_displacement(xy[0] + epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
+ r_deriv[0][0] += uv[0] - r_uv[0];
+ r_deriv[1][0] += uv[1] - r_uv[1];
+ ++num;
+ }
+ if (read_displacement(xy[0] - epsilon[0], xy[1], xs, ys, xy, uv[0], uv[1])) {
+ r_deriv[0][0] += r_uv[0] - uv[0];
+ r_deriv[1][0] += r_uv[1] - uv[1];
+ ++num;
+ }
+ if (num > 0) {
+ float numinv = 1.0f / (float)num;
+ r_deriv[0][0] *= numinv;
+ r_deriv[1][0] *= numinv;
+ }
- /* EWA filtering (without nearest it gets blurry with NO distortion) */
- this->m_inputColorProgram->readFiltered(output, u, v, dxt, dyt, COM_PS_NEAREST);
+ num = 0;
+ if (read_displacement(xy[0], xy[1] + epsilon[1], xs, ys, xy, uv[0], uv[1])) {
+ r_deriv[0][1] += uv[0] - r_uv[0];
+ r_deriv[1][1] += uv[1] - r_uv[1];
+ ++num;
+ }
+ if (read_displacement(xy[0], xy[1] - epsilon[1], xs, ys, xy, uv[0], uv[1])) {
+ r_deriv[0][1] += r_uv[0] - uv[0];
+ r_deriv[1][1] += r_uv[1] - uv[1];
+ ++num;
+ }
+ if (num > 0) {
+ float numinv = 1.0f / (float)num;
+ r_deriv[0][1] *= numinv;
+ r_deriv[1][1] *= numinv;
+ }
}
void DisplaceOperation::deinitExecution()
@@ -126,10 +164,10 @@ bool DisplaceOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffer
/* vector */
operation = getInputOperation(1);
- vectorInput.xmax = input->xmax + 2;
- vectorInput.xmin = input->xmin;
- vectorInput.ymax = input->ymax + 2;
- vectorInput.ymin = input->ymin;
+ vectorInput.xmax = input->xmax + 1;
+ vectorInput.xmin = input->xmin - 1;
+ vectorInput.ymax = input->ymax + 1;
+ vectorInput.ymin = input->ymin - 1;
if (operation->determineDependingAreaOfInterest(&vectorInput, readOperation, output)) {
return true;
}
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.h b/source/blender/compositor/operations/COM_DisplaceOperation.h
index daf54294aa1..cec7937d9d6 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.h
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.h
@@ -48,7 +48,9 @@ public:
/**
* the inner loop of this program
*/
- void executePixel(float output[4], int x, int y, void *data);
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+ void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]);
/**
* Initialize the execution
@@ -59,5 +61,8 @@ public:
* Deinitialize the execution
*/
void deinitExecution();
+
+private:
+ bool read_displacement(float x, float y, float xscale, float yscale, const float origin[2], float &r_u, float &r_v);
};
#endif
diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
index d7cc2ec9272..bc1a6848a57 100644
--- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp
@@ -38,7 +38,7 @@ void EllipseMaskOperation::initExecution()
{
this->m_inputMask = this->getInputSocketReader(0);
this->m_inputValue = this->getInputSocketReader(1);
- const double rad = DEG2RAD((double)this->m_data->rotation);
+ const double rad = (double)this->m_data->rotation;
this->m_cosine = cos(rad);
this->m_sine = sin(rad);
this->m_aspectRatio = ((float)this->getWidth()) / this->getHeight();
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp
index adc325de377..353d6e8f6ce 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_ImageOperation.cpp
@@ -148,7 +148,7 @@ static void sampleImageAtLocation(ImBuf *ibuf, float x, float y, PixelSampler sa
void ImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) {
zero_v4(output);
}
else {
@@ -160,7 +160,7 @@ void ImageAlphaOperation::executePixelSampled(float output[4], float x, float y,
{
float tempcolor[4];
- if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) {
output[0] = 0.0f;
}
else {
@@ -172,11 +172,15 @@ void ImageAlphaOperation::executePixelSampled(float output[4], float x, float y,
void ImageDepthOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- if (this->m_depthBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ if (this->m_depthBuffer == NULL) {
output[0] = 0.0f;
}
else {
- int offset = y * this->m_width + x;
- output[0] = this->m_depthBuffer[offset];
+ if (x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight())
+ output[0] = 0.0f;
+ else {
+ int offset = y * this->m_width + x;
+ output[0] = this->m_depthBuffer[offset];
+ }
}
}
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp
index 289b447dec7..292f073548a 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cpp
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp
@@ -42,46 +42,28 @@ void MapUVOperation::initExecution()
void MapUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float inputUV[4];
- float uv_a[4], uv_b[4];
- float u, v;
+ float xy[2] = { x, y };
+ float uv[2], deriv[2][2], alpha;
- float dx, dy;
- float uv_l, uv_r;
- float uv_u, uv_d;
-
- this->m_inputUVProgram->readSampled(inputUV, x, y, sampler);
- if (inputUV[2] == 0.f) {
+ pixelTransform(xy, uv, deriv, alpha);
+ if (alpha == 0.0f) {
zero_v4(output);
return;
}
- /* adaptive sampling, red (U) channel */
- this->m_inputUVProgram->readSampled(uv_a, x - 1, y, COM_PS_NEAREST);
- this->m_inputUVProgram->readSampled(uv_b, x + 1, y, COM_PS_NEAREST);
- uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
- uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
-
- dx = 0.5f * (uv_l + uv_r);
-
- /* adaptive sampling, green (V) channel */
- this->m_inputUVProgram->readSampled(uv_a, x, y - 1, COM_PS_NEAREST);
- this->m_inputUVProgram->readSampled(uv_b, x, y + 1, COM_PS_NEAREST);
- uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
- uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
-
- dy = 0.5f * (uv_u + uv_d);
+ /* EWA filtering */
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+
/* UV to alpha threshold */
const float threshold = this->m_alpha * 0.05f;
- float alpha = 1.0f - threshold * (dx + dy);
- if (alpha < 0.f) alpha = 0.f;
- else alpha *= inputUV[2];
-
- /* EWA filtering */
- u = inputUV[0] * this->m_inputColorProgram->getWidth();
- v = inputUV[1] * this->m_inputColorProgram->getHeight();
-
- this->m_inputColorProgram->readFiltered(output, u, v, dx, dy, COM_PS_NEAREST);
+ /* XXX alpha threshold is used to fade out pixels on boundaries with invalid derivatives.
+ * this calculation is not very well defined, should be looked into if it becomes a problem ...
+ */
+ float du = len_v2(deriv[0]);
+ float dv = len_v2(deriv[1]);
+ float factor = 1.0f - threshold * (du + dv);
+ if (factor < 0.f) alpha = 0.f;
+ else alpha *= factor;
/* "premul" */
if (alpha < 1.0f) {
@@ -89,6 +71,74 @@ void MapUVOperation::executePixelSampled(float output[4], float x, float y, Pixe
}
}
+bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha)
+{
+ float width = m_inputUVProgram->getWidth();
+ float height = m_inputUVProgram->getHeight();
+ if (x < 0.0f || x >= width || y < 0.0f || y >= height) {
+ r_u = 0.0f;
+ r_v = 0.0f;
+ r_alpha = 0.0f;
+ return false;
+ }
+ else {
+ float col[4];
+ m_inputUVProgram->readSampled(col, x, y, COM_PS_BILINEAR);
+ r_u = col[0] * width;
+ r_v = col[1] * height;
+ r_alpha = col[2];
+ return true;
+ }
+}
+
+void MapUVOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha)
+{
+ float uv[2], alpha; /* temporary variables for derivative estimation */
+ int num;
+
+ read_uv(xy[0], xy[1], r_uv[0], r_uv[1], r_alpha);
+
+ /* Estimate partial derivatives using 1-pixel offsets */
+ const float epsilon[2] = { 1.0f, 1.0f };
+
+ zero_v2(r_deriv[0]);
+ zero_v2(r_deriv[1]);
+
+ num = 0;
+ if (read_uv(xy[0] + epsilon[0], xy[1], uv[0], uv[1], alpha)) {
+ r_deriv[0][0] += uv[0] - r_uv[0];
+ r_deriv[1][0] += uv[1] - r_uv[1];
+ ++num;
+ }
+ if (read_uv(xy[0] - epsilon[0], xy[1], uv[0], uv[1], alpha)) {
+ r_deriv[0][0] += r_uv[0] - uv[0];
+ r_deriv[1][0] += r_uv[1] - uv[1];
+ ++num;
+ }
+ if (num > 0) {
+ float numinv = 1.0f / (float)num;
+ r_deriv[0][0] *= numinv;
+ r_deriv[1][0] *= numinv;
+ }
+
+ num = 0;
+ if (read_uv(xy[0], xy[1] + epsilon[1], uv[0], uv[1], alpha)) {
+ r_deriv[0][1] += uv[0] - r_uv[0];
+ r_deriv[1][1] += uv[1] - r_uv[1];
+ ++num;
+ }
+ if (read_uv(xy[0], xy[1] - epsilon[1], uv[0], uv[1], alpha)) {
+ r_deriv[0][1] += r_uv[0] - uv[0];
+ r_deriv[1][1] += r_uv[1] - uv[1];
+ ++num;
+ }
+ if (num > 0) {
+ float numinv = 1.0f / (float)num;
+ r_deriv[0][1] *= numinv;
+ r_deriv[1][1] *= numinv;
+ }
+}
+
void MapUVOperation::deinitExecution()
{
this->m_inputUVProgram = NULL;
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.h b/source/blender/compositor/operations/COM_MapUVOperation.h
index fe8bfd2a9ac..796ee952607 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.h
+++ b/source/blender/compositor/operations/COM_MapUVOperation.h
@@ -46,7 +46,9 @@ public:
* the inner loop of this program
*/
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
-
+
+ void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2], float &r_alpha);
+
/**
* Initialize the execution
*/
@@ -58,5 +60,9 @@ public:
void deinitExecution();
void setAlpha(float alpha) { this->m_alpha = alpha; }
+
+private:
+ bool read_uv(float x, float y, float &r_u, float &r_v, float &r_alpha);
};
+
#endif
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
index 5b75113e7f3..dcb5ca06662 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
@@ -90,7 +90,7 @@ void MovieClipBaseOperation::executePixelSampled(float output[4], float x, float
{
ImBuf *ibuf = this->m_movieClipBuffer;
- if (ibuf == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ if (ibuf == NULL) {
zero_v4(output);
}
else if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
index a8c7728160d..bc792244dcb 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
@@ -29,7 +29,7 @@ extern "C" {
}
-vector<DistortionCache *> s_cache;
+static vector<DistortionCache *> s_cache;
void deintializeDistortionCache(void)
{
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 84c1fdfb6f5..ffa319f20a8 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -44,9 +44,7 @@ ImBuf *MultilayerBaseOperation::getImBuf()
void MultilayerColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- int yi = y;
- int xi = x;
- if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL) {
zero_v4(output);
}
else {
@@ -64,34 +62,48 @@ void MultilayerColorOperation::executePixelSampled(float output[4], float x, flo
}
}
else {
- int offset = (yi * this->getWidth() + xi) * 3;
- copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
+ int yi = y;
+ int xi = x;
+ if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight())
+ zero_v4(output);
+ else {
+ int offset = (yi * this->getWidth() + xi) * 3;
+ copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
+ }
}
}
}
void MultilayerValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- int yi = y;
- int xi = x;
- if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL) {
output[0] = 0.0f;
}
else {
- float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi];
- output[0] = result;
+ int yi = y;
+ int xi = x;
+ if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight())
+ output[0] = 0.0f;
+ else {
+ float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi];
+ output[0] = result;
+ }
}
}
void MultilayerVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- int yi = y;
- int xi = x;
- if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL) {
output[0] = 0.0f;
}
else {
- int offset = (yi * this->getWidth() + xi) * 3;
- copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
+ int yi = y;
+ int xi = x;
+ if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight())
+ output[0] = 0.0f;
+ else {
+ int offset = (yi * this->getWidth() + xi) * 3;
+ copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
+ }
}
}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
index dba3a6f3505..7780023c465 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
@@ -36,60 +36,17 @@ extern "C" {
#include "BKE_tracking.h"
}
-BLI_INLINE bool isPointInsideQuad(const float x, const float y, const float corners[4][2])
-{
- float point[2];
-
- point[0] = x;
- point[1] = y;
-
- return isect_point_tri_v2(point, corners[0], corners[1], corners[2]) ||
- isect_point_tri_v2(point, corners[0], corners[2], corners[3]);
-}
-
-BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2])
+BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2])
{
float vec[3] = {x, y, 1.0f};
mul_m3_v3(matrix, vec);
- vec[0] /= vec[2];
- vec[1] /= vec[2];
+ uv[0] = vec[0] / vec[2];
+ uv[1] = vec[1] / vec[2];
- copy_v2_v2(uv, vec);
-}
-
-BLI_INLINE void resolveUVAndDxDy(const float x, const float y, float matrix[3][3],
- float *u_r, float *v_r, float *dx_r, float *dy_r)
-{
- float inputUV[2];
- float uv_a[2], uv_b[2];
-
- float dx, dy;
- float uv_l, uv_r;
- float uv_u, uv_d;
-
- warpCoord(x, y, matrix, inputUV);
-
- /* adaptive sampling, red (U) channel */
- warpCoord(x - 1, y, matrix, uv_a);
- warpCoord(x + 1, y, matrix, uv_b);
- uv_l = fabsf(inputUV[0] - uv_a[0]);
- uv_r = fabsf(inputUV[0] - uv_b[0]);
-
- dx = 0.5f * (uv_l + uv_r);
-
- /* adaptive sampling, green (V) channel */
- warpCoord(x, y - 1, matrix, uv_a);
- warpCoord(x, y + 1, matrix, uv_b);
- uv_u = fabsf(inputUV[1] - uv_a[1]);
- uv_d = fabsf(inputUV[1] - uv_b[1]);
-
- dy = 0.5f * (uv_u + uv_d);
-
- *dx_r = dx;
- *dy_r = dy;
-
- *u_r = inputUV[0];
- *v_r = inputUV[1];
+ deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2];
+ deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2];
+ deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2];
+ deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2];
}
PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation()
@@ -98,9 +55,6 @@ PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonO
this->addOutputSocket(COM_DT_COLOR);
this->m_pixelReader = NULL;
this->setComplex(true);
-
- /* Currently hardcoded to 8 samples. */
- this->m_osa = 8;
}
void PlaneTrackWarpImageOperation::initExecution()
@@ -109,8 +63,6 @@ void PlaneTrackWarpImageOperation::initExecution()
this->m_pixelReader = this->getInputSocketReader(0);
- BLI_jitter_init(this->m_jitter[0], this->m_osa);
-
const int width = this->m_pixelReader->getWidth();
const int height = this->m_pixelReader->getHeight();
float frame_corners[4][2] = {{0.0f, 0.0f},
@@ -127,41 +79,32 @@ void PlaneTrackWarpImageOperation::deinitExecution()
this->m_pixelReader = NULL;
}
-void PlaneTrackWarpImageOperation::executePixelSampled(float output[4], float x_, float y_, PixelSampler sampler)
+void PlaneTrackWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float color_accum[4];
+ float xy[2] = {x, y};
+ float uv[2];
+ float deriv[2][2];
- zero_v4(color_accum);
- for (int sample = 0; sample < this->m_osa; sample++) {
- float current_x = x_ + this->m_jitter[sample][0],
- current_y = y_ + this->m_jitter[sample][1];
- if (isPointInsideQuad(current_x, current_y, this->m_frameSpaceCorners)) {
- float current_color[4];
- float u, v, dx, dy;
+ pixelTransform(xy, uv, deriv);
- resolveUVAndDxDy(current_x, current_y, m_perspectiveMatrix, &u, &v, &dx, &dy);
-
- /* derivatives are to be in normalized space.. */
- dx /= this->m_pixelReader->getWidth();
- dy /= this->m_pixelReader->getHeight();
-
- this->m_pixelReader->readFiltered(current_color, u, v, dx, dy, COM_PS_NEAREST);
- add_v4_v4(color_accum, current_color);
- }
- }
+ m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+}
- mul_v4_v4fl(output, color_accum, 1.0f / this->m_osa);
+void PlaneTrackWarpImageOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
+{
+ warpCoord(xy[0], xy[1], m_perspectiveMatrix, r_uv, r_deriv);
}
bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
float UVs[4][2];
+ float deriv[2][2];
/* TODO(sergey): figure out proper way to do this. */
- warpCoord(input->xmin - 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[0]);
- warpCoord(input->xmax + 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[1]);
- warpCoord(input->xmax + 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[2]);
- warpCoord(input->xmin - 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[3]);
+ warpCoord(input->xmin - 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[0], deriv);
+ warpCoord(input->xmax + 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[1], deriv);
+ warpCoord(input->xmax + 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[2], deriv);
+ warpCoord(input->xmin - 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[3], deriv);
float min[2], max[2];
INIT_MINMAX2(min, max);
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
index ed9cc2fe5aa..ceb002c8039 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
@@ -36,8 +36,6 @@
class PlaneTrackWarpImageOperation : public PlaneTrackCommonOperation {
protected:
SocketReader *m_pixelReader;
- int m_osa;
- float m_jitter[32][2];
float m_perspectiveMatrix[3][3];
public:
@@ -47,6 +45,7 @@ public:
void deinitExecution();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]);
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
};
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
index b93e338ad6c..47d5fc6bcca 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
@@ -81,14 +81,16 @@ void ReadBufferOperation::executePixelExtend(float output[4], float x, float y,
}
}
-void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx, float dy, PixelSampler sampler)
+void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler)
{
if (m_single_value) {
/* write buffer has a single value stored at (0,0) */
m_buffer->read(output, 0, 0);
}
else {
- m_buffer->readEWA(output, x, y, dx, dy, sampler);
+ const float uv[2] = { x, y };
+ const float deriv[2][2] = { {dx[0], dx[1]}, {dy[0], dy[1]} };
+ m_buffer->readEWA(output, uv, deriv, sampler);
}
}
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index cdc6e50f6d4..cce519c6eb3 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -43,7 +43,7 @@ public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
void executePixelExtend(float output[4], float x, float y, PixelSampler sampler,
MemoryBufferExtend extend_x, MemoryBufferExtend extend_y);
- void executePixelFiltered(float output[4], float x, float y, float dx, float dy, PixelSampler sampler);
+ void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler);
const bool isReadBufferOperation() const { return true; }
void setOffset(unsigned int offset) { this->m_offset = offset; }
unsigned int getOffset() const { return this->m_offset; }
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 2c2a4c6f180..f72af2780d7 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -75,13 +75,15 @@ void RenderLayersBaseProg::initExecution()
void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
{
unsigned int offset;
- int ix, iy;
int width = this->getWidth(), height = this->getHeight();
switch (sampler) {
- case COM_PS_NEAREST:
- ix = x;
- iy = y;
+ case COM_PS_NEAREST: {
+ int ix = x;
+ int iy = y;
+ if (ix < 0 || iy < 0 || ix >= width || iy >= height)
+ break;
+
offset = (iy * width + ix) * this->m_elementsize;
if (this->m_elementsize == 1)
@@ -90,8 +92,8 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi
copy_v3_v3(output, &this->m_inputBuffer[offset]);
else
copy_v4_v4(output, &this->m_inputBuffer[offset]);
-
break;
+ }
case COM_PS_BILINEAR:
BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
@@ -137,7 +139,7 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y
int iy = y;
#endif
- if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
+ if (this->m_inputBuffer == NULL) {
zero_v4(output);
}
else {
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 1d9022e463b..75363f4f567 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -342,7 +342,7 @@ static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
}
/* name property for ID block entries */
-static short acf_generic_idblock_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
RNA_id_pointer_create(ale->id, ptr);
*prop = RNA_struct_name_property(ptr->type);
@@ -352,7 +352,7 @@ static short acf_generic_idblock_nameprop(bAnimListElem *ale, PointerRNA *ptr, P
/* name property for ID block entries which are just subheading "fillers" */
-static short acf_generic_idfill_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
/* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
RNA_id_pointer_create(ale->data, ptr);
@@ -365,19 +365,19 @@ static short acf_generic_idfill_nameprop(bAnimListElem *ale, PointerRNA *ptr, Pr
#if 0
/* channel type has no settings */
-static short acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
+static bool acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
{
- return 0;
+ return false;
}
#endif
/* check if some setting exists for this object-based data-expander (datablock only) */
-static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
+static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* expand is always supported */
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
/* mute is only supported for NLA */
case ACHANNEL_SETTING_MUTE:
@@ -385,11 +385,11 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle
/* select is ok for most "ds*" channels (e.g. dsmat) */
case ACHANNEL_SETTING_SELECT:
- return 1;
+ return true;
/* other flags are never supported */
default:
- return 0;
+ return false;
}
}
@@ -438,23 +438,23 @@ static int acf_summary_icon(bAnimListElem *UNUSED(ale))
}
/* check if some setting exists for this channel */
-static short acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
/* only expanded is supported, as it is used for hiding all stuff which the summary covers */
return (setting == ACHANNEL_SETTING_EXPAND);
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
if (setting == ACHANNEL_SETTING_EXPAND) {
/* expanded */
- *neg = 1;
+ *neg = true;
return ADS_FLAG_SUMMARY_COLLAPSED;
}
else {
/* unsupported */
- *neg = 0;
+ *neg = false;
return 0;
}
}
@@ -509,7 +509,7 @@ static int acf_scene_icon(bAnimListElem *UNUSED(ale))
}
/* check if some setting exists for this channel */
-static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
+static bool acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* muted only in NLA */
@@ -523,32 +523,32 @@ static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale
/* only select and expand supported otherwise */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return SCE_DS_SELECTED;
case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = 1;
+ *neg = true;
return SCE_DS_COLLAPSED;
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
default: /* unsupported */
@@ -593,7 +593,7 @@ static bAnimChannelType ACF_SCENE =
NULL, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_scene_icon, /* icon */
acf_scene_setting_valid, /* has setting */
@@ -649,7 +649,7 @@ static void acf_object_name(bAnimListElem *ale, char *name)
}
/* check if some setting exists for this channel */
-static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
+static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
{
Base *base = (Base *)ale->data;
Object *ob = base->object;
@@ -666,18 +666,18 @@ static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int
/* only select and expand supported otherwise */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_object_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_object_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -691,7 +691,7 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
default: /* unsupported */
@@ -737,7 +737,7 @@ static bAnimChannelType ACF_OBJECT =
NULL, /* offset */
acf_object_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_object_icon, /* icon */
acf_object_setting_valid, /* has setting */
@@ -803,7 +803,7 @@ static void acf_group_name(bAnimListElem *ale, char *name)
}
/* name property for group entries */
-static short acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
@@ -812,28 +812,28 @@ static short acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
}
/* check if some setting exists for this channel */
-static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
+static bool acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
{
/* for now, all settings are supported, though some are only conditionally */
switch (setting) {
/* unsupported */
case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
- return 0;
+ return false;
/* conditionally supported */
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
return (ac->spacetype == SPACE_IPO);
default: /* always supported */
- return 1;
+ return true;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_group_setting_flag(bAnimContext *ac, int setting, short *neg)
+static int acf_group_setting_flag(bAnimContext *ac, int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -854,7 +854,6 @@ static int acf_group_setting_flag(bAnimContext *ac, int setting, short *neg)
return AGRP_MUTED;
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to edtiability
return AGRP_PROTECTED;
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
@@ -903,7 +902,7 @@ static void acf_fcurve_name(bAnimListElem *ale, char *name)
}
/* "name" property for fcurve entries */
-static short acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
FCurve *fcu = (FCurve *)ale->data;
@@ -924,7 +923,7 @@ static short acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyR
}
/* check if some setting exists for this channel */
-static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
+static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
{
FCurve *fcu = (FCurve *)ale->data;
@@ -932,29 +931,29 @@ static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int
/* unsupported */
case ACHANNEL_SETTING_SOLO: /* Solo Flag is only for NLA */
case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
- return 0;
+ return false;
/* conditionally available */
case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
if (fcu->bezt)
- return 1;
+ return true;
else
- return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
+ return false; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
return (ac->spacetype == SPACE_IPO);
/* always available */
default:
- return 1;
+ return true;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -964,7 +963,6 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return FCURVE_MUTED;
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to edtiability
return FCURVE_PROTECTED;
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
@@ -1012,31 +1010,31 @@ static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
}
/* check if some setting exists for this channel */
-static short acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* only select and expand supported */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = 1;
+ *neg = true;
return ACT_COLLAPSED;
default: /* unsupported */
@@ -1079,7 +1077,7 @@ static bAnimChannelType ACF_FILLACTD =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_fillactd_icon, /* icon */
acf_fillactd_setting_valid, /* has setting */
@@ -1102,27 +1100,27 @@ static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
/* check if some setting exists for this channel */
// TODO: this could be made more generic
-static short acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* only expand supported */
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
- *neg = 1;
+ *neg = true;
return ADT_DRIVERS_COLLAPSED;
default: /* unsupported */
@@ -1176,10 +1174,10 @@ static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1189,7 +1187,7 @@ static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1235,7 +1233,7 @@ static bAnimChannelType ACF_DSMAT =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsmat_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1252,10 +1250,10 @@ static int acf_dslam_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1265,7 +1263,7 @@ static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1311,7 +1309,7 @@ static bAnimChannelType ACF_DSLAM =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dslam_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1335,10 +1333,10 @@ static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(al
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1348,7 +1346,7 @@ static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1394,7 +1392,7 @@ static bAnimChannelType ACF_DSTEX =
acf_dstex_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_dstex_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1411,10 +1409,10 @@ static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1424,7 +1422,7 @@ static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1470,7 +1468,7 @@ static bAnimChannelType ACF_DSCAM =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_dscam_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1497,10 +1495,10 @@ static int acf_dscur_icon(bAnimListElem *ale)
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1510,7 +1508,7 @@ static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1556,7 +1554,7 @@ static bAnimChannelType ACF_DSCUR =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dscur_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1573,10 +1571,10 @@ static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1586,7 +1584,7 @@ static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1632,7 +1630,7 @@ static bAnimChannelType ACF_DSSKEY =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsskey_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1649,10 +1647,10 @@ static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1662,7 +1660,7 @@ static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1708,7 +1706,7 @@ static bAnimChannelType ACF_DSWOR =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_dswor_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1725,10 +1723,10 @@ static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1738,7 +1736,7 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1784,7 +1782,7 @@ static bAnimChannelType ACF_DSPART =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dspart_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1801,10 +1799,10 @@ static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1814,7 +1812,7 @@ static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1860,7 +1858,7 @@ static bAnimChannelType ACF_DSMBALL =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsmball_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1877,10 +1875,10 @@ static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1890,7 +1888,7 @@ static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -1936,7 +1934,7 @@ static bAnimChannelType ACF_DSARM =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsarm_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -1964,10 +1962,10 @@ static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -1977,7 +1975,7 @@ static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2023,7 +2021,7 @@ static bAnimChannelType ACF_DSNTREE =
acf_dsntree_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsntree_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -2040,10 +2038,10 @@ static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -2053,7 +2051,7 @@ static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), int setting, s
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2099,7 +2097,7 @@ static bAnimChannelType ACF_DSLINESTYLE =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dslinestyle_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -2116,10 +2114,10 @@ static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -2129,7 +2127,7 @@ static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), int setting, short
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2175,7 +2173,7 @@ static bAnimChannelType ACF_DSMESH =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsmesh_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -2192,10 +2190,10 @@ static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -2205,7 +2203,7 @@ static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2251,7 +2249,7 @@ static bAnimChannelType ACF_DSLAT =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dslat_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -2268,10 +2266,10 @@ static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
@@ -2281,7 +2279,7 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short *
return ADT_NLA_EVAL_OFF;
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
- *neg = 1;
+ *neg = true;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2327,7 +2325,7 @@ static bAnimChannelType ACF_DSSPK =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idblock_nameprop, /* name prop */
+ acf_generic_idblock_name_prop, /* name prop */
acf_dsspk_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@@ -2353,7 +2351,7 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name)
}
/* name property for ShapeKey entries */
-static short acf_shapekey_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
KeyBlock *kb = (KeyBlock *)ale->data;
@@ -2365,29 +2363,29 @@ static short acf_shapekey_nameprop(bAnimListElem *ale, PointerRNA *ptr, Property
return (*prop != NULL);
}
- return 0;
+ return false;
}
/* check if some setting exists for this channel */
-static short acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted */
case ACHANNEL_SETTING_PROTECT: /* protected */
- return 1;
+ return true;
/* nothing else is supported */
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_MUTE: /* mute */
@@ -2434,7 +2432,7 @@ static bAnimChannelType ACF_SHAPEKEY =
acf_generic_basic_offset, /* offset */
acf_shapekey_name, /* name */
- acf_shapekey_nameprop, /* name prop */
+ acf_shapekey_name_prop, /* name prop */
NULL, /* icon */
acf_shapekey_setting_valid, /* has setting */
@@ -2458,24 +2456,24 @@ static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
}
/* check if some setting exists for this channel */
-static short acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* only select and expand supported */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2509,7 +2507,7 @@ static bAnimChannelType ACF_GPD =
acf_generic_group_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_gpd_icon, /* icon */
acf_gpd_setting_valid, /* has setting */
@@ -2529,7 +2527,7 @@ static void acf_gpl_name(bAnimListElem *ale, char *name)
}
/* name property for grease pencil layer entries */
-static short acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
@@ -2538,30 +2536,30 @@ static short acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA
return (*prop != NULL);
}
- return 0;
+ return false;
}
/* check if some setting exists for this channel */
-static short acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* unsupported */
case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
- return 0;
+ return false;
/* always available */
default:
- return 1;
+ return true;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2571,7 +2569,6 @@ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *ne
return GP_LAYER_HIDE;
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to editability
return GP_LAYER_LOCKED;
default: /* unsupported */
@@ -2624,24 +2621,24 @@ static int acf_mask_icon(bAnimListElem *UNUSED(ale))
}
/* check if some setting exists for this channel */
-static short acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* only select and expand supported */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -2675,7 +2672,7 @@ static bAnimChannelType ACF_MASKDATA =
acf_generic_group_offset, /* offset */
acf_generic_idblock_name, /* name */
- acf_generic_idfill_nameprop, /* name prop */
+ acf_generic_idfill_name_prop, /* name prop */
acf_mask_icon, /* icon */
acf_mask_setting_valid, /* has setting */
@@ -2695,7 +2692,7 @@ static void acf_masklay_name(bAnimListElem *ale, char *name)
}
/* name property for grease pencil layer entries */
-static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
@@ -2704,40 +2701,36 @@ static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, Property
return (*prop != NULL);
}
- return 0;
+ return false;
}
/* check if some setting exists for this channel */
-static short acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
switch (setting) {
/* unsupported */
case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
case ACHANNEL_SETTING_SOLO: /* nla editor only */
- return 0;
+ return false;
/* always available */
default:
- return 1;
+ return true;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return MASK_LAYERFLAG_SELECT;
-// case ACHANNEL_SETTING_MUTE: /* muted */
-// return GP_LAYER_HIDE;
-
case ACHANNEL_SETTING_PROTECT: /* protected */
- // *neg = 1; - if we change this to editability
return MASK_LAYERFLAG_LOCKED;
default: /* unsupported */
@@ -2804,7 +2797,7 @@ static void acf_nlatrack_name(bAnimListElem *ale, char *name)
}
/* name property for nla track entries */
-static short acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
@@ -2813,11 +2806,11 @@ static short acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, Propert
return (*prop != NULL);
}
- return 0;
+ return false;
}
/* check if some setting exists for this channel */
-static short acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *ale, int setting)
+static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *ale, int setting)
{
NlaTrack *nlt = (NlaTrack *)ale->data;
AnimData *adt = ale->adt;
@@ -2827,7 +2820,7 @@ static short acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem
/* always supported */
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_SOLO:
- return 1;
+ return true;
/* conditionally supported... */
case ACHANNEL_SETTING_PROTECT:
@@ -2838,34 +2831,34 @@ static short acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem
if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
if (nlt->flag & NLATRACK_SOLO) {
/* ok - we've got a solo track, and this is it */
- return 1;
+ return true;
}
else {
/* not ok - we've got a solo track, but this isn't it, so make it more obvious */
- return 0;
+ return false;
}
}
/* ok - no tracks are solo'd, and this isn't being tweaked */
- return 1;
+ return true;
}
else {
/* unsupported - this track is being tweaked */
- return 0;
+ return false;
}
/* unsupported */
default:
- return 0;
+ return false;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), int setting, bool *neg)
{
/* clear extra return data first */
- *neg = 0;
+ *neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
@@ -3037,7 +3030,8 @@ short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, int setting
/* 1) check that the setting exists for the current context */
if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
/* 2) get pointer to check for flag in, and the flag to check for */
- short negflag, ptrsize;
+ short ptrsize;
+ bool negflag;
int flag;
void *ptr;
@@ -3112,7 +3106,8 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, int setting,
/* 1) check that the setting exists for the current context */
if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
/* 2) get pointer to check for flag in, and the flag to check for */
- short negflag, ptrsize;
+ short ptrsize;
+ bool negflag;
int flag;
void *ptr;
@@ -3494,7 +3489,8 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf,
uiBlock *block, int xpos, int ypos, int setting)
{
- short negflag, ptrsize /* , enabled */ /* UNUSED */, butType;
+ short ptrsize, butType;
+ bool negflag;
int flag, icon;
void *ptr;
const char *tooltip;
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 33ca10420ec..861998c15f3 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2152,7 +2152,8 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
bAnimContext ac;
rcti rect;
short selectmode = 0;
- int gesture_mode, extend;
+ int gesture_mode;
+ bool extend;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index cab072675b2..9818c312e8e 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -125,11 +125,11 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
{
TimeMarker *marker;
float cfra = (float)CFRA;
- int changed = 0;
+ int changed_tot = 0;
/* sanity check */
if (markers == NULL)
- return changed;
+ return changed_tot;
/* affect selected markers - it's unlikely that we will want to affect all in this way? */
for (marker = markers->first; marker; marker = marker->next) {
@@ -144,7 +144,7 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
(side == 'R' && marker->frame >= cfra))
{
marker->frame += (int)floorf(value + 0.5f);
- changed++;
+ changed_tot++;
}
break;
}
@@ -152,14 +152,14 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
{
/* rescale the distance between the marker and the current frame */
marker->frame = cfra + (int)floorf(((float)(marker->frame - cfra) * value) + 0.5f);
- changed++;
+ changed_tot++;
break;
}
}
}
}
- return changed;
+ return changed_tot;
}
/* --------------------------------- */
@@ -173,7 +173,7 @@ TimeMarker *ED_markers_find_nearest_marker(ListBase *markers, float x)
if (markers) {
for (marker = markers->first; marker; marker = marker->next) {
- dist = ABS((float)marker->frame - x);
+ dist = fabsf((float)marker->frame - x);
if (dist < min_dist) {
min_dist = dist;
@@ -1083,7 +1083,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
bool camera = false;
#ifdef DURIAN_CAMERA_SWITCH
camera = RNA_boolean_get(op->ptr, "camera");
@@ -1148,7 +1148,7 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
TimeMarker *marker;
float xminf, xmaxf, yminf, ymaxf;
int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
- int extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
rcti rect;
WM_operator_properties_border_to_rcti(op, &rect);
@@ -1270,7 +1270,7 @@ static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
ListBase *markers = ED_context_get_markers(C);
TimeMarker *marker, *nmarker;
- short changed = 0;
+ bool changed = false;
if (markers == NULL)
return OPERATOR_CANCELLED;
@@ -1279,7 +1279,7 @@ static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
nmarker = marker->next;
if (marker->flag & SELECT) {
BLI_freelinkN(markers, marker);
- changed = 1;
+ changed = true;
}
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index cfa5f9f032c..481012bf411 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -104,12 +104,13 @@ void delete_fcurve_key(FCurve *fcu, int index, short do_recalc)
}
/* Delete selected keyframes in given F-Curve */
-void delete_fcurve_keys(FCurve *fcu)
+bool delete_fcurve_keys(FCurve *fcu)
{
int i;
+ bool changed = false;
if (fcu->bezt == NULL) /* ignore baked curves */
- return;
+ return false;
/* Delete selected BezTriples */
for (i = 0; i < fcu->totvert; i++) {
@@ -117,12 +118,15 @@ void delete_fcurve_keys(FCurve *fcu)
memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
fcu->totvert--;
i--;
+ changed = true;
}
}
/* Free the array of BezTriples if there are not keyframes */
if (fcu->totvert == 0)
clear_fcurve_keys(fcu);
+
+ return changed;
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 1028fb30ba4..07cc16aa5b6 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1474,8 +1474,10 @@ void ANIM_OT_keyframe_delete(wmOperatorType *ot)
* it is more useful for animators working in the 3D view.
*/
-static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
+static int clear_anim_v3d_exec(bContext *C, wmOperator *op)
{
+ int num_deleted = 0;
+
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
/* just those in active action... */
@@ -1515,15 +1517,19 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
/* delete F-Curve completely */
if (can_delete) {
ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+ num_deleted++;
}
}
}
-
+
/* update... */
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
-
+
+ if (num_deleted > 0)
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d animation F-Curves from selected objects", num_deleted);
+
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
@@ -1538,7 +1544,6 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
ot->idname = "ANIM_OT_keyframe_clear_v3d";
/* callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = clear_anim_v3d_exec;
ot->poll = ED_operator_areaactive;
@@ -1602,7 +1607,6 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
ot->idname = "ANIM_OT_keyframe_delete_v3d";
/* callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = delete_key_v3d_exec;
ot->poll = ED_operator_areaactive;
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 1a0841f5342..ca2dc1b66e2 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -27,7 +27,6 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
- ../../../../intern/opennl/extern
)
set(INC_SYS
@@ -67,4 +66,11 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_OPENNL)
+ add_definitions(-DWITH_OPENNL)
+ list(APPEND INC_SYS
+ ../../../../intern/opennl/extern
+ )
+endif()
+
blender_add_lib(bf_editor_armature "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index b91deab6c8d..ed8ae2d4cbb 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -789,11 +789,13 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
copy_v3_v3(newbone->tail, ebone->tail);
copy_v3_v3(ebone->tail, newbone->head);
- newbone->rad_head = 0.5f * (ebone->rad_head + ebone->rad_tail);
+ newbone->rad_head = ((ebone->rad_head * cutratio) + (ebone->rad_tail * cutratioI));
ebone->rad_tail = newbone->rad_head;
newbone->flag |= BONE_CONNECTED;
-
+
+ newbone->prop = NULL;
+
unique_editbone_name(arm->edbo, newbone->name, NULL);
/* correct parent bones */
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 1bc5bf0fd74..c284769ff5c 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -989,6 +989,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
bArmature *arm = (bArmature *)ob->data;
EditBone *actbone = CTX_data_active_bone(C);
EditBone *actmirb = NULL;
+ int num_selected_bones;
/* there must be an active bone */
if (actbone == NULL) {
@@ -1011,7 +1012,8 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
/* if there is only 1 selected bone, we assume that that is the active bone,
* since a user will need to have clicked on a bone (thus selecting it) to make it active
*/
- if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
+ if (num_selected_bones <= 1) {
/* When only the active bone is selected, and it has a parent,
* align it to the parent, as that is the only possible outcome.
*/
@@ -1020,6 +1022,8 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
+
+ BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
}
}
else {
@@ -1042,8 +1046,10 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op)
}
}
CTX_DATA_END;
+
+ BKE_reportf(op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
}
-
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
@@ -1058,7 +1064,6 @@ void ARMATURE_OT_align(wmOperatorType *ot)
ot->description = "Align selected bones to the active bone (or to their parent)";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = armature_align_bones_exec;
ot->poll = ED_operator_editarmature;
@@ -1108,12 +1113,13 @@ void ARMATURE_OT_split(wmOperatorType *ot)
/* previously delete_armature */
/* only editmode! */
-static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
+static int armature_delete_selected_exec(bContext *C, wmOperator *op)
{
bArmature *arm;
EditBone *curBone, *ebone_next;
bConstraint *con;
Object *obedit = CTX_data_edit_object(C); // XXX get from context
+ int num_deleted = 0;
arm = obedit->data;
/* cancel if nothing selected */
@@ -1170,10 +1176,12 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
if (curBone->flag & BONE_SELECTED) {
if (curBone == arm->act_edbone) arm->act_edbone = NULL;
ED_armature_edit_bone_remove(arm, curBone);
+ num_deleted++;
}
}
}
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d bones", num_deleted);
ED_armature_sync_selection(arm->edbo);
@@ -1190,7 +1198,6 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
ot->description = "Remove selected bones from the armature";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = armature_delete_selected_exec;
ot->poll = ED_operator_editarmature;
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index bc7d69d1558..f3db9042879 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -68,6 +68,7 @@ void ARMATURE_OT_select_less(struct wmOperatorType *ot);
void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
void ARMATURE_OT_select_similar(struct wmOperatorType *ot);
+void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot);
void ARMATURE_OT_delete(struct wmOperatorType *ot);
void ARMATURE_OT_duplicate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index c574fc6a297..a4b40f64859 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -232,14 +232,33 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
/* fix modifiers that might be using this name */
for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *)md;
-
- /* uses armature, so may use the affected bone name */
- if (hmd->object && (hmd->object->data == arm)) {
- if (!strcmp(hmd->subtarget, oldname))
- BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
+ switch (md->type) {
+ case eModifierType_Hook:
+ {
+ HookModifierData *hmd = (HookModifierData *)md;
+
+ if (hmd->object && (hmd->object->data == arm)) {
+ if (STREQ(hmd->subtarget, oldname))
+ BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
+ }
+ break;
+ }
+ case eModifierType_UVWarp:
+ {
+ UVWarpModifierData *umd = (UVWarpModifierData *)md;
+
+ if (umd->object_src && (umd->object_src->data == arm)) {
+ if (STREQ(umd->bone_src, oldname))
+ BLI_strncpy(umd->bone_src, newname, MAXBONENAME);
+ }
+ if (umd->object_dst && (umd->object_dst->data == arm)) {
+ if (STREQ(umd->bone_dst, oldname))
+ BLI_strncpy(umd->bone_dst, newname, MAXBONENAME);
+ }
+ break;
}
+ default:
+ break;
}
}
}
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index 4c7eb847054..feb9b0f939a 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -64,6 +64,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(ARMATURE_OT_select_hierarchy);
WM_operatortype_append(ARMATURE_OT_select_linked);
WM_operatortype_append(ARMATURE_OT_select_similar);
+ WM_operatortype_append(ARMATURE_OT_shortest_path_pick);
WM_operatortype_append(ARMATURE_OT_delete);
WM_operatortype_append(ARMATURE_OT_duplicate);
@@ -264,6 +265,8 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "ARMATURE_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "ARMATURE_OT_shortest_path_pick", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_delete", DELKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index cd24e94f9e9..087e9a86241 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -454,7 +454,7 @@ static void separate_armature_bones(Object *ob, short sel)
}
/* separate selected bones into their armature */
-static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op))
+static int separate_armature_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -520,6 +520,8 @@ static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op))
ED_armature_to_edit(obedit);
+ BKE_report(op->reports, RPT_INFO, "Separated bones");
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
@@ -537,7 +539,6 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
ot->description = "Isolate selected bones into a separate armature";
/* callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = separate_armature_exec;
ot->poll = ED_operator_editarmature;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 003f6bf36f3..ed2d1388196 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -174,7 +174,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
{
bArmature *arm;
EditBone *bone, *curBone, *next;
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
Object *obedit = CTX_data_edit_object(C);
arm = obedit->data;
@@ -1120,3 +1120,123 @@ void ARMATURE_OT_select_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
+
+
+/****************** Select Path ****************/
+
+static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child,
+ bool use_parent, bool is_test)
+{
+ do {
+
+ if (!use_parent && (ebone_child == ebone_parent))
+ break;
+
+ if (is_test) {
+ if (!EBONE_SELECTABLE(arm, ebone_child)) {
+ return false;
+ }
+ }
+ else {
+ ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
+ }
+
+ if (ebone_child == ebone_parent)
+ break;
+
+ ebone_child = ebone_child->parent;
+ } while (true);
+
+ return true;
+}
+
+static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_src, *ebone_dst;
+ EditBone *ebone_isect_parent = NULL;
+ EditBone *ebone_isect_child[2];
+ bool changed;
+
+ view3d_operator_needs_opengl(C);
+
+ ebone_src = arm->act_edbone;
+ ebone_dst = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
+
+ /* fallback to object selection */
+ if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ ebone_isect_child[0] = ebone_src;
+ ebone_isect_child[1] = ebone_dst;
+
+
+ /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
+ if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
+ /* pass */
+ }
+ else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
+ SWAP(EditBone *, ebone_src, ebone_dst);
+ }
+ else if ((ebone_isect_parent = ED_armature_bone_find_shared_parent(ebone_isect_child, 2))) {
+ /* pass */
+ }
+ else {
+ /* disconnected bones */
+ return OPERATOR_CANCELLED;
+ }
+
+
+ if (ebone_isect_parent) {
+ if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true))
+ {
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
+ armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+ else {
+ if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
+ armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
+ changed = true;
+ }
+ else {
+ /* unselectable */
+ changed = false;
+ }
+ }
+
+ if (changed) {
+ arm->act_edbone = ebone_dst;
+ ED_armature_sync_selection(arm->edbo);
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Pick Shortest Path";
+ ot->idname = "ARMATURE_OT_shortest_path_pick";
+ ot->description = "Select shortest path between two bones";
+
+ /* api callbacks */
+ ot->invoke = armature_shortest_path_pick_invoke;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 5f15d15d478..7ec0acf12d1 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -386,9 +386,13 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
/* compute the weights based on gathered vertices and bones */
if (heat) {
const char *error = NULL;
+
+#ifdef WITH_OPENNL
heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
root, tip, selected, &error);
-
+#else
+ error = "Built without OpenNL";
+#endif
if (error) {
BKE_report(reports, RPT_WARNING, error);
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 2cbfb52db91..7d6b3710a38 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -156,6 +156,47 @@ bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebon
return false;
}
+/**
+ * Finds the first parent shared by \a ebone_child
+ *
+ * \param ebone_child Children bones to search
+ * \param ebone_child_tot Size of the ebone_child array
+ * \return The shared parent or NULL.
+ */
+EditBone *ED_armature_bone_find_shared_parent(EditBone *ebone_child[], const unsigned int ebone_child_tot)
+{
+ unsigned int i;
+ EditBone *ebone_iter;
+
+#define EBONE_TEMP_UINT(ebone) (*((unsigned int *)(&((ebone)->temp))))
+
+ /* clear all */
+ for (i = 0; i < ebone_child_tot; i++) {
+ for (ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
+ EBONE_TEMP_UINT(ebone_iter) = 0;
+ }
+ }
+
+ /* accumulate */
+ for (i = 0; i < ebone_child_tot; i++) {
+ ebone_iter = ebone_child[i];
+ for (ebone_iter = ebone_child[i]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
+ EBONE_TEMP_UINT(ebone_iter) += 1;
+ }
+ }
+
+ /* only need search the first chain */
+ for (ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent) {
+ if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
+ return ebone_iter;
+ }
+ }
+
+#undef EBONE_TEMP_UINT
+
+ return NULL;
+}
+
void ED_armature_ebone_to_mat3(EditBone *ebone, float mat[3][3])
{
float delta[3];
@@ -460,6 +501,7 @@ void ED_armature_from_edit(Object *obedit)
/* armature bones */
BKE_armature_bonelist_free(&arm->bonebase);
+ arm->act_bone = NULL;
/* remove zero sized bones, this gives unstable restposes */
for (eBone = arm->edbo->first; eBone; eBone = neBone) {
@@ -593,7 +635,6 @@ void ED_armature_to_edit(Object *ob)
ED_armature_edit_free(ob);
arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
- arm->act_bone = NULL;
// BIF_freeTemplates(); /* force template update when entering editmode */
}
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index c03e7861307..2c00c5e646c 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -697,7 +697,7 @@ static int RIG_parentControl(RigControl *ctrl, EditBone *link)
static void RIG_reconnectControlBones(RigGraph *rg)
{
RigControl *ctrl;
- int change = 1;
+ bool changed = true;
/* first pass, link to deform bones */
for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
@@ -812,8 +812,8 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* second pass, make chains in control bones */
- while (change) {
- change = 0;
+ while (changed) {
+ changed = false;
for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next) {
/* if control is not linked yet */
@@ -865,7 +865,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* check if parent is already linked */
if (ctrl_parent && ctrl_parent->link) {
RIG_parentControl(ctrl, ctrl_parent->bone);
- change = 1;
+ changed = true;
}
else {
/* check childs */
@@ -873,7 +873,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* if a child is linked, link to that one */
if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone) {
RIG_parentControl(ctrl, ctrl_child->bone);
- change = 1;
+ changed = true;
break;
}
}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 16d7f9c9420..3b285e12331 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -46,13 +46,14 @@
#include "BLI_polardecomp.h"
#endif
-#include "ONL_opennl.h"
-
#include "ED_mesh.h"
#include "ED_armature.h"
#include "meshlaplacian.h"
+#ifdef WITH_OPENNL
+
+#include "ONL_opennl.h"
/* ************* XXX *************** */
static void waitcursor(int UNUSED(val)) {}
@@ -2006,3 +2007,13 @@ void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexco
waitcursor(0);
}
+#else /* WITH_OPENNL */
+
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+void mesh_deform_bind(Scene *scene, MeshDeformModifierData *mmd, float *vertexcos, int totvert, float cagemat[4][4]) {}
+void *modifier_mdef_compact_influences_link_kludge = modifier_mdef_compact_influences;
+
+#endif /* WITH_OPENNL */
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 69ee794e1d9..ce10214c2ee 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -105,7 +105,7 @@ static int poselib_get_free_index(bAction *act)
{
TimeMarker *marker;
int low = 0, high = 0;
- short changed = 0;
+ bool changed = false;
/* sanity checks */
if (ELEM(NULL, act, act->markers.first)) return 1;
@@ -115,7 +115,7 @@ static int poselib_get_free_index(bAction *act)
* Prevents problems with deleting then trying to add new poses [#27412]
*/
do {
- changed = 0;
+ changed = false;
for (marker = act->markers.first; marker; marker = marker->next) {
/* only increase low if value is 1 greater than low, to find "gaps" where
@@ -123,13 +123,13 @@ static int poselib_get_free_index(bAction *act)
*/
if (marker->frame == (low + 1)) {
low++;
- changed = 1;
+ changed = true;
}
/* value replaces high if it is the highest value encountered yet */
if (marker->frame > high) {
high = marker->frame;
- changed = 1;
+ changed = true;
}
}
} while (changed != 0);
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 765437f3622..34023d365ca 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -180,7 +180,10 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
* (e.g. Mask Modifier in 'Armature' mode), force update
*/
else if (arm->flag & ARM_HAS_VIZ_DEPS) {
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ /* NOTE: ob not ob_act here is intentional - it's the source of the
+ * bones being selected [T37247]
+ */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
@@ -263,7 +266,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = (bArmature *)ob->data;
Bone *bone, *curBone, *next = NULL;
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
view3d_operator_needs_opengl(C);
@@ -625,13 +628,13 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot)
/* -------------------------------------- */
-static short pose_select_same_group(bContext *C, Object *ob, bool extend)
+static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
{
bArmature *arm = (ob) ? ob->data : NULL;
bPose *pose = (ob) ? ob->pose : NULL;
char *group_flags;
int numGroups = 0;
- short changed = 0, tagged = 0;
+ bool changed = false, tagged = false;
/* sanity checks */
if (ELEM3(NULL, ob, pose, arm))
@@ -653,7 +656,7 @@ static short pose_select_same_group(bContext *C, Object *ob, bool extend)
/* keep track of group as group to use later? */
if (pchan->bone->flag & BONE_SELECTED) {
group_flags[pchan->agrp_index] = 1;
- tagged = 1;
+ tagged = true;
}
/* deselect all bones before selecting new ones? */
@@ -671,7 +674,7 @@ static short pose_select_same_group(bContext *C, Object *ob, bool extend)
/* check if the group used by this bone is counted */
if (group_flags[pchan->agrp_index]) {
pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
+ changed = true;
}
}
}
@@ -684,11 +687,11 @@ static short pose_select_same_group(bContext *C, Object *ob, bool extend)
return changed;
}
-static short pose_select_same_layer(bContext *C, Object *ob, bool extend)
+static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
{
bPose *pose = (ob) ? ob->pose : NULL;
bArmature *arm = (ob) ? ob->data : NULL;
- short changed = 0;
+ bool changed = false;
int layers = 0;
if (ELEM3(NULL, ob, pose, arm))
@@ -715,7 +718,7 @@ static short pose_select_same_layer(bContext *C, Object *ob, bool extend)
/* if bone is on a suitable layer, and the bone can have its selection changed, select it */
if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
@@ -723,14 +726,14 @@ static short pose_select_same_layer(bContext *C, Object *ob, bool extend)
return changed;
}
-static int pose_select_same_keyingset(bContext *C, Object *ob, bool extend)
+static bool pose_select_same_keyingset(bContext *C, Object *ob, bool extend)
{
KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
KS_Path *ksp;
bArmature *arm = (ob) ? ob->data : NULL;
bPose *pose = (ob) ? ob->pose : NULL;
- short changed = 0;
+ bool changed = false;
/* sanity checks: validate Keying Set and object */
if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
@@ -765,7 +768,7 @@ static int pose_select_same_keyingset(bContext *C, Object *ob, bool extend)
/* select if bone is visible and can be affected */
if (PBONE_SELECTABLE(arm, pchan->bone)) {
pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
+ changed = true;
}
}
@@ -783,8 +786,8 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op)
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = (bArmature *)ob->data;
- short extend = RNA_boolean_get(op->ptr, "extend");
- short changed = 0;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool changed = false;
/* sanity check */
if (ob->pose == NULL)
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index da8f86580f6..3ee83c20852 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -118,6 +118,8 @@ void CURVE_OT_vertex_add(struct wmOperatorType *ot);
void CURVE_OT_extrude(struct wmOperatorType *ot);
void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
+void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
+
/* helper functions */
void ed_editnurb_translate_flag(struct ListBase *editnurb, short flag, const float vec[3]);
bool ed_editnurb_extrude_flag(struct EditNurb *editnurb, short flag);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 1cf194e02c4..e978b81523f 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -137,6 +137,8 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_vertex_add);
WM_operatortype_append(CURVE_OT_extrude);
WM_operatortype_append(CURVE_OT_cyclic_toggle);
+
+ WM_operatortype_append(CURVE_OT_match_texture_space);
}
void ED_operatormacros_curve(void)
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index f576440fe92..caa06eb15d0 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -47,6 +47,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -2307,11 +2308,12 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
BezTriple *bezt, *beztOrig;
BPoint *bp, *bpOrig;
float val, newval, offset;
- int a, i, change = 0;
+ int a, i;
+ bool changed = false;
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->bezt) {
- change = 0;
+ changed = false;
beztOrig = MEM_dupallocN(nu->bezt);
for (bezt = &nu->bezt[1], a = 1; a < nu->pntsu - 1; a++, bezt++) {
if (bezt->f2 & SELECT) {
@@ -2324,12 +2326,13 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
bezt->vec[0][i] += offset;
bezt->vec[2][i] += offset;
}
- change = 1;
+ changed = true;
}
}
MEM_freeN(beztOrig);
- if (change)
+ if (changed) {
BKE_nurb_handles_calc(nu);
+ }
}
else if (nu->bp) {
bpOrig = MEM_dupallocN(nu->bp);
@@ -3568,7 +3571,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
- bool change = false;
+ bool changed = false;
const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
const int type = RNA_enum_get(op->ptr, "type");
@@ -3582,11 +3585,11 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
if (BKE_nurb_type_convert(nu, type, use_handles) == false)
BKE_report(op->reports, RPT_ERROR, "No conversion possible");
else
- change = true;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
@@ -4364,7 +4367,7 @@ bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3],
Curve *cu = (Curve *)obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
- float si, phi, n[3], q[4], cmat[3][3], tmat[3][3], imat[3][3];
+ float cmat[3][3], tmat[3][3], imat[3][3];
float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
float persmat[3][3], persinv[3][3];
bool ok, changed = false;
@@ -4377,15 +4380,7 @@ bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3],
copy_m3_m4(bmat, obedit->obmat);
invert_m3_m3(imat, bmat);
- normalize_v3_v3(n, axis);
- /* TODO - use math func */
- phi = M_PI / 8.0;
- q[0] = cos(phi);
- si = sin(phi);
- q[1] = n[0] * si;
- q[2] = n[1] * si;
- q[3] = n[2] * si;
- quat_to_mat3(cmat, q);
+ axis_angle_to_mat3(cmat, axis, M_PI / 4.0);
mul_m3_m3m3(tmat, cmat, bmat);
mul_m3_m3m3(rotmat, imat, tmat);
@@ -6367,7 +6362,7 @@ static int curve_delete_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
Curve *cu = (Curve *)obedit->data;
eCurveElem_Types type = RNA_enum_get(op->ptr, "type");
- int retval;
+ int retval = OPERATOR_CANCELLED;
if (type == CURVE_VERTEX) retval = curve_delete_vertices(obedit);
else if (type == CURVE_SEGMENT) retval = curve_delete_segments(obedit, false);
@@ -6813,3 +6808,65 @@ int ED_curve_actSelection(Curve *cu, float center[3])
return 1;
}
+
+/******************** Match texture space operator ***********************/
+
+static int match_texture_space_poll(bContext *C)
+{
+ Object *object = CTX_data_active_object(C);
+
+ return object && ELEM3(object->type, OB_CURVE, OB_SURF, OB_FONT);
+}
+
+static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *object = CTX_data_active_object(C);
+ Curve *curve = (Curve *) object->data;
+ float min[3], max[3], size[3], loc[3];
+ int a;
+
+ if (ELEM(NULL, object->curve_cache, object->curve_cache->disp.first)) {
+ BKE_displist_make_curveTypes(scene, object, FALSE);
+ }
+
+ INIT_MINMAX(min, max);
+ BKE_displist_minmax(&object->curve_cache->disp, min, max);
+
+ mid_v3_v3v3(loc, min, max);
+
+ size[0] = (max[0] - min[0]) / 2.0f;
+ size[1] = (max[1] - min[1]) / 2.0f;
+ size[2] = (max[2] - min[2]) / 2.0f;
+
+ for (a = 0; a < 3; a++) {
+ if (size[a] == 0.0f) size[a] = 1.0f;
+ else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f;
+ else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f;
+ }
+
+ copy_v3_v3(curve->loc, loc);
+ copy_v3_v3(curve->size, size);
+ zero_v3(curve->rot);
+
+ curve->texflag &= ~CU_AUTOSPACE;
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve);
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_match_texture_space(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Match Texture Space";
+ ot->idname = "CURVE_OT_match_texture_space";
+ ot->description = "Match texture space to object's bounding box";
+
+ /* api callbacks */
+ ot->exec = match_texture_space_exec;
+ ot->poll = match_texture_space_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 8f536575a28..baedc7ecf25 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -780,6 +780,9 @@ static int paste_selection(Object *obedit, ReportList *reports)
/* Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT */
if (cu->len + len <= MAXTEXT) {
+
+ kill_selection(obedit, 0);
+
if (len) {
int size = (cu->len * sizeof(wchar_t)) - (cu->pos * sizeof(wchar_t)) + sizeof(wchar_t);
memmove(ef->textbuf + cu->pos + len, ef->textbuf + cu->pos, size);
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index aee97f40c31..a03a80bfbbc 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -209,21 +209,24 @@ void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short
/* Frame Editing Tools */
/* Delete selected frames */
-void ED_gplayer_frames_delete(bGPDlayer *gpl)
+bool ED_gplayer_frames_delete(bGPDlayer *gpl)
{
bGPDframe *gpf, *gpfn;
+ bool changed = false;
/* error checking */
if (gpl == NULL)
- return;
+ return false;
/* check for frames to delete */
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
if (gpf->flag & GP_FRAME_SELECT)
- gpencil_layer_delframe(gpl, gpf);
+ changed |= gpencil_layer_delframe(gpl, gpf);
}
+
+ return changed;
}
/* Duplicate selected frames from given gp-layer */
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index cdf9b71972d..a3d3d8f05a2 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -53,7 +53,7 @@
* color, while not being endian-sensitive. On little-endians, this
* is the same as doing a 'naive' indexing, on big-endian, it is not!
* */
-#define cpack(x) glColor3ub( ((x) & 0xFF), (((x) >> 8) & 0xFF), (((x) >> 16) & 0xFF) )
+void cpack(unsigned int x);
#define glMultMatrixf(x) glMultMatrixf( (float *)(x))
#define glLoadMatrixf(x) glLoadMatrixf( (float *)(x))
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index d98fa1fc32f..8b9bb0a4ab0 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -396,15 +396,15 @@ typedef struct bAnimChannelType {
/* get name (for channel lists) */
void (*name)(bAnimListElem *ale, char *name);
/* get RNA property+pointer for editing the name */
- short (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
+ bool (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
/* get icon (for channel lists) */
int (*icon)(bAnimListElem *ale);
/* settings */
/* check if the given setting is valid in the current context */
- short (*has_setting)(bAnimContext *ac, bAnimListElem *ale, int setting);
+ bool (*has_setting)(bAnimContext *ac, bAnimListElem *ale, int setting);
/* get the flag used for this setting */
- int (*setting_flag)(bAnimContext *ac, int setting, short *neg);
+ int (*setting_flag)(bAnimContext *ac, int setting, bool *neg);
/* get the pointer to int/short where data is stored,
* with type being sizeof(ptr_data) which should be fine for runtime use...
* - assume that setting has been checked to be valid for current context
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 455378fc2ce..e9caf89d9da 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -138,6 +138,7 @@ struct EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *na
void ED_armature_edit_bone_remove(struct bArmature *arm, EditBone *exBone);
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
+EditBone *ED_armature_bone_find_shared_parent(EditBone *ebone_child[], const unsigned int ebone_child_tot);
void ED_armature_ebone_to_mat3(EditBone *ebone, float mat[3][3]);
void ED_armature_ebone_to_mat4(EditBone *ebone, float mat[4][4]);
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index cb4a81be8b8..4e05c6c9fb6 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -95,7 +95,7 @@ void ED_gplayer_frames_select_border(struct bGPDlayer *gpl, float min, float ma
void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode);
void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode);
-void ED_gplayer_frames_delete(struct bGPDlayer *gpl);
+bool ED_gplayer_frames_delete(struct bGPDlayer *gpl);
void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl);
void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode);
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 3020fe6985a..5718a70208e 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -237,7 +237,7 @@ void bezt_remap_times(KeyframeEditData *ked, struct BezTriple *bezt);
/* Destructive Editing API (keyframes_general.c) */
void delete_fcurve_key(struct FCurve *fcu, int index, short do_recalc);
-void delete_fcurve_keys(struct FCurve *fcu);
+bool delete_fcurve_keys(struct FCurve *fcu);
void clear_fcurve_keys(struct FCurve *fcu);
void duplicate_fcurve_keys(struct FCurve *fcu);
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 8da36f015dc..3f8d571b239 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -68,8 +68,8 @@ void ED_mask_draw_frames(struct Mask *mask, struct ARegion *ar, const int cfra,
/* mask_shapekey.c */
void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame);
-int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
-int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
+bool ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
+bool ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
/* ----------- Mask AnimEdit API ------------------ */
short ED_masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene,
@@ -82,7 +82,7 @@ void ED_masklayer_frames_select_border(struct MaskLayer *masklay, float min, fl
void ED_mask_select_frames(struct MaskLayer *masklay, short select_mode);
void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mode);
-void ED_masklayer_frames_delete(struct MaskLayer *masklay);
+bool ED_masklayer_frames_delete(struct MaskLayer *masklay);
void ED_masklayer_frames_duplicate(struct MaskLayer *masklay);
void ED_masklayer_snap_frames(struct MaskLayer *masklay, struct Scene *scene, short mode);
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index e85f11e5b78..ed7415e6c26 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -65,8 +65,20 @@ void ED_keymap_paint(struct wmKeyConfig *keyconf);
#define UNDO_PAINT_IMAGE 0
#define UNDO_PAINT_MESH 1
+typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
+typedef void (*UndoFreeCb)(struct ListBase *lb);
+
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_free(void);
int ED_undo_paint_valid(int type, const char *name);
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free);
+void ED_undo_paint_push_end(int type);
+
+/* image painting specific undo */
+void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
+void ED_image_undo_free(struct ListBase *lb);
+void ED_imapaint_clear_partial_redraw(void);
+void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+
#endif
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index dde1aa30a26..35f12a47f82 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -121,8 +121,9 @@ struct ReportList;
void BIF_clearTransformOrientation(struct bContext *C);
void BIF_removeTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
void BIF_removeTransformOrientationIndex(struct bContext *C, int index);
-void BIF_createTransformOrientation(struct bContext *C, struct ReportList *reports, char *name, int use_view,
- int use, int overwrite);
+void BIF_createTransformOrientation(struct bContext *C, struct ReportList *reports,
+ const char *name, const bool use_view,
+ const bool activate, const bool overwrite);
void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
void BIF_selectTransformOrientationValue(struct bContext *C, int orientation);
@@ -143,6 +144,7 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_OPTIONS (1 << 7)
#define P_CORRECT_UV (1 << 8)
#define P_NO_DEFAULTS (1 << 10)
+#define P_NO_TEXSPACE (1 << 11)
void Transform_Properties(struct wmOperatorType *ot, int flags);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 0f3106794f5..f155247f851 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -85,6 +85,8 @@ typedef struct ViewDepths {
float *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d);
void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
+struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
+
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist);
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist);
@@ -216,6 +218,9 @@ bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d,
float *r_clipsta, float *r_clipend, const bool use_ortho_factor);
bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi,
struct rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize);
+
+void ED_view3d_polygon_offset(const struct RegionView3D *rv3d, const float dist);
+
void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar,
struct View3D *v3d, struct RegionView3D *rv3d,
struct rctf *r_viewborder, const bool no_shift);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 50e2e53dbf0..e931aad2722 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -93,7 +93,7 @@ typedef struct uiLayout uiLayout;
/* use for clamping popups within the screen */
#define UI_SCREEN_MARGIN 10
-/* uiBlock->dt */
+/* uiBlock->dt and uiBut->dt */
#define UI_EMBOSS 0 /* use widget style for drawing */
#define UI_EMBOSSN 1 /* Nothing, only icon and/or text */
#define UI_EMBOSSP 2 /* Pulldown menu style */
@@ -130,8 +130,7 @@ typedef struct uiLayout uiLayout;
#define UI_BLOCK_POPUP_MEMORY (1 << 12)
#define UI_BLOCK_CLIP_EVENTS (1 << 13) /* stop handling mouse events */
-/* XXX This comment is no more valid! Maybe it is now bits 14-17? */
-/* block->flag bits 12-15 are identical to but->flag bits */
+/* block->flag bits 14-17 are identical to but->drawflag bits */
#define UI_BLOCK_LIST_ITEM (1 << 19)
@@ -148,46 +147,55 @@ typedef struct uiLayout uiLayout;
#define UI_PNL_CLOSE (1 << 5)
#define UI_PNL_SCALE (1 << 9)
-/* warning the first 6 flags are internal */
-/* but->flag */
-#define UI_TEXT_LEFT (1 << 6)
-#define UI_ICON_LEFT (1 << 7)
-#define UI_ICON_SUBMENU (1 << 8)
-#define UI_ICON_PREVIEW (1 << 9)
-
-#define UI_TEXT_RIGHT (1 << 10)
-#define UI_BUT_NODE_LINK (1 << 11)
-#define UI_BUT_NODE_ACTIVE (1 << 12)
-#define UI_BUT_DRAG_LOCK (1 << 13)
-
-/* button align flag, for drawing groups together */
-#define UI_BUT_ALIGN (UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT | UI_BUT_ALIGN_DOWN)
-#define UI_BUT_ALIGN_TOP (1 << 14)
-#define UI_BUT_ALIGN_LEFT (1 << 15)
-#define UI_BUT_ALIGN_RIGHT (1 << 16)
-#define UI_BUT_ALIGN_DOWN (1 << 17)
-
-#define UI_BUT_DISABLED (1 << 18)
-#define UI_BUT_COLOR_LOCK (1 << 19)
-#define UI_BUT_ANIMATED (1 << 20)
-#define UI_BUT_ANIMATED_KEY (1 << 21)
-#define UI_BUT_DRIVEN (1 << 22)
-#define UI_BUT_REDALERT (1 << 23)
-#define UI_BUT_INACTIVE (1 << 24)
-#define UI_BUT_LAST_ACTIVE (1 << 25)
-#define UI_BUT_UNDO (1 << 26)
-#define UI_BUT_IMMEDIATE (1 << 27)
-#define UI_BUT_NO_TOOLTIP (1 << 28)
-#define UI_BUT_NO_UTF8 (1 << 29)
-
-#define UI_BUT_VEC_SIZE_LOCK (1 << 30) /* used to flag if color hsv-circle should keep luminance */
-#define UI_BUT_COLOR_CUBIC (1 << 31) /* cubic saturation for the color wheel */
+/* but->flag - general state flags. */
+enum {
+ /* warning, the first 6 flags are internal */
+ UI_ICON_SUBMENU = (1 << 6),
+ UI_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). */
+};
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
-/* uiBut->drawflag */
-#define UI_BUT_DRAW_ENUM_ARROWS (1 << 0) /* draw enum-like up/down arrows for button */
+/* but->drawflag - these flags should only affect how the button is drawn. */
+/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions
+ * (except for the 'align' ones)!
+ */
+enum {
+ /* draw enum-like up/down arrows for button */
+ UI_BUT_DRAW_ENUM_ARROWS = (1 << 0),
+ /* Text and icon alignment (by default, they are centered). */
+ UI_BUT_TEXT_LEFT = (1 << 1),
+ UI_BUT_ICON_LEFT = (1 << 2),
+ UI_BUT_TEXT_RIGHT = (1 << 3),
+ /* Prevent the button to show any tooltip. */
+ UI_BUT_NO_TOOLTIP = (1 << 4),
+ /* button align flag, for drawing groups together (also used in uiBlock->flag!) */
+ UI_BUT_ALIGN_TOP = (1 << 14),
+ UI_BUT_ALIGN_LEFT = (1 << 15),
+ UI_BUT_ALIGN_RIGHT = (1 << 16),
+ UI_BUT_ALIGN_DOWN = (1 << 17),
+ UI_BUT_ALIGN = (UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT | UI_BUT_ALIGN_DOWN),
+};
/* scale fixed button widths by this to account for DPI */
@@ -259,7 +267,6 @@ typedef enum {
PROGRESSBAR = (51 << 9),
SEARCH_MENU_UNLINK = (52 << 9),
NODESOCKET = (53 << 9),
- LISTLABEL = (54 << 9),
} eButType;
#define BUTTYPE (63 << 9)
@@ -314,7 +321,7 @@ typedef struct uiSearchItems uiSearchItems;
typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2);
typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr);
typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
-typedef bool (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
+typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
@@ -425,7 +432,6 @@ void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
int UI_but_active_drop_name(struct bContext *C);
-struct uiBut *ui_but_find_mouse_over(struct ARegion *ar, int x, int y);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -468,7 +474,6 @@ uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, i
uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip);
uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip);
uiBut *uiDefButO_ptr(uiBlock *block, int type, struct wmOperatorType *ot, int opcontext, const char *str, int x, int y, short width, short height, const char *tip);
-uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip);
uiBut *uiDefIconBut(uiBlock *block,
int type, int retval, int icon,
@@ -628,8 +633,9 @@ void uiBlockSetDrawExtraFunc(uiBlock *block,
void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect),
void *arg1, void *arg2);
-bool UI_textbutton_activate_event(const struct bContext *C, struct ARegion *ar,
- const void *rna_poin_data, const char *rna_prop_id);
+bool UI_textbutton_activate_rna(const struct bContext *C, struct ARegion *ar,
+ const void *rna_poin_data, const char *rna_prop_id);
+bool UI_textbutton_activate_but(const struct bContext *C, uiBut *but);
void uiButSetFocusOnEnter(struct wmWindow *win, uiBut *but);
@@ -681,6 +687,7 @@ void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers)
void UI_init(void);
void UI_init_userdef(void);
+void UI_init_userdef_factory(void);
void UI_reinit_font(void);
void UI_exit(void);
@@ -896,9 +903,9 @@ void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct Prop
/* Styled text draw */
void uiStyleFontSet(struct uiFontStyle *fs);
void uiStyleFontDrawExt(struct uiFontStyle *fs, const struct rcti *rect, const char *str,
- float *r_xofs, float *r_yofs);
-void uiStyleFontDraw(struct uiFontStyle *fs, struct rcti *rect, const char *str);
-void uiStyleFontDrawRotated(struct uiFontStyle *fs, struct rcti *rect, const char *str);
+ size_t len, float *r_xofs, float *r_yofs);
+void uiStyleFontDraw(struct uiFontStyle *fs, const struct rcti *rect, const char *str);
+void uiStyleFontDrawRotated(struct uiFontStyle *fs, const struct rcti *rect, const char *str);
int UI_GetStringWidth(const char *str); // XXX temp
void UI_DrawString(float x, float y, const char *str); // XXX temp
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 0c8a39a6714..af0df0e0643 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -144,9 +144,17 @@ enum {
TH_EMPTY,
TH_NODE,
- TH_NODE_IN_OUT,
+ TH_NODE_INPUT,
+ TH_NODE_OUTPUT,
+ TH_NODE_COLOR,
+ TH_NODE_FILTER,
+ TH_NODE_VECTOR,
+ TH_NODE_TEXTURE,
+ TH_NODE_PATTERN,
+ TH_NODE_SCRIPT,
+ TH_NODE_LAYOUT,
+ TH_NODE_SHADER,
TH_NODE_INTERFACE,
- TH_NODE_OPERATOR,
TH_NODE_CONVERTOR,
TH_NODE_GROUP,
TH_NODE_FRAME,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index c9a19ab4d8e..da26b3d71a4 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -155,7 +155,7 @@ void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
void UI_view2d_totRect_set_resize(struct View2D *v2d, int width, int height, int resize);
/* per tab offsets, returns 1 if tab changed */
-int UI_view2d_tab_set(struct View2D *v2d, int tab);
+bool UI_view2d_tab_set(struct View2D *v2d, int tab);
/* view matrix operations */
void UI_view2d_view_ortho(struct View2D *v2d);
@@ -208,7 +208,7 @@ short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d,
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
void UI_view2d_text_cache_add(struct View2D *v2d, float x, float y, const char *str, const char col[4]);
-void UI_view2d_text_cache_rectf(struct View2D *v2d, struct rctf *rect, const char *str, const char col[4]);
+void UI_view2d_text_cache_rectf(struct View2D *v2d, const struct rctf *rect, const char *str, const char col[4]);
void UI_view2d_text_cache_draw(struct ARegion *ar);
/* operators */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 83b100db1b2..45a73e217fe 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -218,7 +218,7 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
for (bt = block->buttons.first; bt; bt = bt->next) {
if (bt->type != SEPR) {
- j = BLF_width(style->widget.uifont_id, bt->drawstr);
+ j = BLF_width(style->widget.uifont_id, bt->drawstr, sizeof(bt->drawstr));
if (j > i) i = j;
}
@@ -613,6 +613,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
{
/* flags from the buttons we want to refresh, may want to add more here... */
const int flag_copy = UI_BUT_REDALERT;
+ const int drawflag_copy = 0; /* None currently. */
uiBlock *oldblock;
uiBut *oldbut, *but = *butpp;
@@ -670,8 +671,9 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
SWAP(char *, oldbut->poin, but->poin);
SWAP(void *, oldbut->func_argN, but->func_argN);
}
-
+
oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy);
+ oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy);
/* copy hardmin for list rows to prevent 'sticking' highlight to mouse position
* when scrolling without moving mouse (see [#28432]) */
@@ -2436,36 +2438,47 @@ void ui_check_but(uiBut *but)
case NUMSLI:
if (!but->editstr) {
+ const char *drawstr_suffix = NULL;
+ size_t slen;
+
UI_GET_BUT_VALUE_INIT(but, value);
+ slen = BLI_strncpy_rlen(but->drawstr, but->str, sizeof(but->drawstr));
+
if (ui_is_but_float(but)) {
if (value == (double) FLT_MAX) {
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%sinf", but->str);
+ slen += BLI_strncpy_rlen(but->drawstr + slen, "inf", sizeof(but->drawstr) - slen);
}
else if (value == (double) -FLT_MAX) {
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s-inf", but->str);
+ slen += BLI_strncpy_rlen(but->drawstr + slen, "-inf", sizeof(but->drawstr) - slen);
}
/* support length type buttons */
else if (ui_is_but_unit(but)) {
char new_str[sizeof(but->drawstr)];
ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE, -1);
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str);
+ slen += BLI_strncpy_rlen(but->drawstr + slen, new_str, sizeof(but->drawstr) - slen);
}
else {
const int prec = ui_but_float_precision(but, value);
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value);
+ slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value);
}
}
else {
- BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%d", but->str, (int)value);
+ slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value);
}
if (but->rnaprop) {
PropertySubType pstype = RNA_property_subtype(but->rnaprop);
- if (pstype == PROP_PERCENTAGE)
- strcat(but->drawstr, "%");
+ if (pstype == PROP_PERCENTAGE) {
+ drawstr_suffix = "%";
+ }
+ }
+
+ if (drawstr_suffix) {
+ BLI_strncpy(but->drawstr + slen, drawstr_suffix, sizeof(but->drawstr) - slen);
}
+
}
break;
@@ -2604,7 +2617,7 @@ static void ui_block_do_align_but(uiBut *first, short nr)
next = NULL;
/* clear old flag */
- but->flag &= ~UI_BUT_ALIGN;
+ but->drawflag &= ~UI_BUT_ALIGN;
if (flag == 0) { /* first case */
if (next) {
@@ -2683,7 +2696,7 @@ static void ui_block_do_align_but(uiBut *first, short nr)
}
}
- but->flag |= flag;
+ but->drawflag |= flag;
/* merge coordinates */
if (prev) {
@@ -2863,10 +2876,15 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
if ((block->flag & UI_BLOCK_LOOP) ||
ELEM8(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
{
- but->flag |= (UI_TEXT_LEFT | UI_ICON_LEFT);
+ but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
+ }
+#ifdef USE_NUMBUTS_LR_ALIGN
+ else if (ELEM(but->type, NUM, NUMSLI)) {
+ but->drawflag |= UI_BUT_TEXT_LEFT;
}
+#endif
- but->flag |= (block->flag & UI_BUT_ALIGN);
+ but->drawflag |= (block->flag & UI_BUT_ALIGN);
if (but->lock == TRUE) {
if (but->lockstr) {
@@ -3041,7 +3059,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
if (icon) {
but->icon = (BIFIconID)icon;
but->flag |= UI_HAS_ICON;
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
}
if (!RNA_property_editable(&but->rnapoin, prop)) {
@@ -3110,45 +3128,6 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, int type, wmOperatorType *
return but;
}
-#if 0 /* UNUSED */
-static uiBut *UNUSED_FUNCTION(ui_def_but_operator) (uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
-{
- wmOperatorType *ot = WM_operatortype_find(opname, 0);
- if (str == NULL && ot == NULL) str = opname;
- return ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
-}
-#endif
-
-static uiBut *ui_def_but_operator_text(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but;
- wmOperatorType *ot;
-
- ot = WM_operatortype_find(opname, 0);
-
- if (!str) {
- if (ot) str = ot->name;
- else str = opname;
- }
-
- if ((!tip || tip[0] == '\0') && ot && ot->description) {
- tip = ot->description;
- }
-
- but = ui_def_but(block, type, -1, str, x, y, width, height, poin, min, max, a1, a2, tip);
- but->optype = ot;
- but->opcontext = opcontext;
- but->flag &= ~UI_BUT_UNDO; /* no need for ui_is_but_rna_undo(), we never need undo here */
-
- if (!ot) {
- but->flag |= UI_BUT_DISABLED;
- but->lock = TRUE;
- but->lockstr = "";
- }
-
- return but;
-}
-
uiBut *uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
{
uiBut *but = ui_def_but(block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
@@ -3340,13 +3319,6 @@ uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, co
return uiDefButO_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
}
-uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
-{
- uiBut *but = ui_def_but_operator_text(block, type, opname, opcontext, str, x, y, width, height, poin, min, max, a1, a2, tip);
- ui_check_but(but);
- return but;
-}
-
/* if a1==1.0 then a2 is an extra icon blending factor (alpha 0.0 - 1.0) */
uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
{
@@ -3430,7 +3402,7 @@ uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, const ch
{
uiBut *but = ui_def_but(block, type, retval, str, x, y, width, height, poin, min, max, a1, a2, tip);
ui_check_but_and_iconize(but, icon);
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
@@ -3481,7 +3453,7 @@ uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const c
uiBut *but;
but = ui_def_but_rna_propname(block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip);
ui_check_but_and_iconize(but, icon);
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
@@ -3489,7 +3461,7 @@ uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, co
uiBut *but;
but = ui_def_but_rna(block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip);
ui_check_but_and_iconize(but, icon);
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
@@ -3497,7 +3469,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o
uiBut *but;
but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip);
ui_check_but_and_iconize(but, icon);
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
return but;
}
uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
@@ -3553,7 +3525,7 @@ void uiBlockFlipOrder(uiBlock *block)
return;
for (but = block->buttons.first; but; but = but->next) {
- if (but->flag & UI_BUT_ALIGN) return;
+ if (but->drawflag & UI_BUT_ALIGN) return;
if (but->rect.ymin < miny) miny = but->rect.ymin;
if (but->rect.ymax > maxy) maxy = but->rect.ymax;
}
@@ -3794,7 +3766,7 @@ uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, in
but->icon = (BIFIconID) icon;
but->flag |= UI_HAS_ICON;
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
but->flag |= UI_ICON_SUBMENU;
but->menu_create_func = func;
@@ -3809,7 +3781,7 @@ uiBut *uiDefIconMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int ic
but->icon = (BIFIconID) icon;
but->flag |= UI_HAS_ICON;
- but->flag &= ~UI_ICON_LEFT;
+ but->drawflag &= ~UI_BUT_ICON_LEFT;
but->menu_create_func = func;
ui_check_but(but);
@@ -3825,7 +3797,7 @@ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg,
/* XXX temp, old menu calls pass on icon arrow, which is now UI_ICON_SUBMENU flag */
if (icon != ICON_RIGHTARROW_THIN) {
but->icon = (BIFIconID) icon;
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
}
but->flag |= UI_HAS_ICON;
but->flag |= UI_ICON_SUBMENU;
@@ -3844,7 +3816,7 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int
but->icon = (BIFIconID) icon;
but->flag |= UI_HAS_ICON;
- but->flag |= UI_ICON_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT;
but->block_create_func = func;
ui_check_but(but);
@@ -3879,7 +3851,7 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
but->icon = (BIFIconID) icon;
but->flag |= UI_HAS_ICON;
- but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
ui_check_but(but);
@@ -4016,7 +3988,7 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
const char *tc1, *tc2;
tc1 = strstr(but->str, "%t");
- tc2 = strstr(but->str, "|"); /* XXX For some reason strchr seems to not work here? */
+ tc2 = strstr(but->str, UI_SEP_CHAR_S);
if (tc2 && (!tc1 || tc1 > tc2))
tc1 = tc2;
@@ -4192,6 +4164,11 @@ void UI_init_userdef(void)
uiStyleInit();
}
+void UI_init_userdef_factory(void)
+{
+ init_userdef_factory();
+}
+
void UI_reinit_font(void)
{
uiStyleInit();
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 11062ea2bd2..b6f93726bfc 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -395,7 +395,7 @@ void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
-void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
+void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
#ifdef WITH_HEADLESS
(void)rect;
@@ -526,7 +526,7 @@ static void histogram_draw_one(float r, float g, float b, float alpha,
#define HISTOGRAM_TOT_GRID_LINES 4
-void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Histogram *hist = (Histogram *)but->poin;
int res = hist->x_resolution;
@@ -594,7 +594,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
#undef HISTOGRAM_TOT_GRID_LINES
-void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Scopes *scopes = (Scopes *)but->poin;
rctf rect;
@@ -825,7 +825,7 @@ static void vectorscope_draw_target(float centerx, float centery, float diam, co
glEnd();
}
-void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
Scopes *scopes = (Scopes *)but->poin;
@@ -912,7 +912,7 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glDisable(GL_BLEND);
}
-void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
+void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
ColorBand *coba;
CBData *cbd;
@@ -1037,7 +1037,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
}
-void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
+void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
static GLuint displist = 0;
int a, old[8];
@@ -1130,7 +1130,7 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
}
}
-static void ui_draw_but_curve_grid(rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
+static void ui_draw_but_curve_grid(const rcti *rect, float zoomx, float zoomy, float offsx, float offsy, float step)
{
float dx, dy, fx, fy;
@@ -1163,7 +1163,7 @@ static void gl_shaded_color(unsigned char *col, int shade)
col[2] - shade > 0 ? col[2] - shade : 0);
}
-void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect)
+void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
CurveMapping *cumap;
CurveMap *cuma;
@@ -1362,7 +1362,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect
fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
-void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
rctf rect;
int ok = 0, width, height;
@@ -1488,7 +1488,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glDisable(GL_BLEND);
}
-void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
static const float size = 5.0f;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 2b8b7643f39..61761d7db41 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -60,6 +60,7 @@
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
#include "BKE_unit.h"
@@ -173,6 +174,7 @@ typedef struct uiHandleButtonData {
int draglastx, draglasty;
int dragstartx, dragstarty;
int draglastvalue;
+ int dragstartvalue;
bool dragchange, draglock;
int dragsel;
float dragf, dragfstart;
@@ -235,9 +237,15 @@ typedef struct uiAfterFunc {
+static bool ui_is_but_interactive(uiBut *but, const bool labeledit);
static bool ui_but_contains_pt(uiBut *but, int mx, int my);
static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
+static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, int x, int y, bool ctrl);
+static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event);
+static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
+static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data,
+ const bool mousemove, const bool onfree);
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata);
static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
static void button_timers_tooltip_remove(bContext *C, uiBut *but);
@@ -301,7 +309,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
static bool ui_but_editable(uiBut *but)
{
- return ELEM6(but->type, LABEL, LISTLABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
+ return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
}
static uiBut *ui_but_prev(uiBut *but)
@@ -415,7 +423,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->func_arg2 = but->func_arg2;
after->funcN = but->funcN;
- after->func_argN = MEM_dupallocN(but->func_argN);
+ after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : NULL;
after->rename_func = but->rename_func;
after->rename_arg1 = but->rename_arg1;
@@ -715,7 +723,7 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
{
/* popups such as layers won't re-evaluate on redraw */
const bool do_check = (ar->regiontype == RGN_TYPE_TEMPORARY);
- bool change = false;
+ bool changed = false;
uiBlock *block;
for (block = ar->uiblocks.first; block; block = block->next) {
@@ -728,7 +736,9 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
for (but = block->buttons.first; but; but = but->next) {
- if (ui_is_but_interactive(but)) {
+ /* Note: ctrl is always true here because (at least for now) we always want to consider text control
+ * in this case, even when not embossed. */
+ if (ui_is_but_interactive(but, true)) {
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
/* execute the button */
@@ -741,7 +751,7 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
if (do_check) {
ui_check_but(but);
}
- change = true;
+ changed = true;
}
}
/* done */
@@ -751,7 +761,7 @@ static bool ui_drag_toggle_set_xy_xy(bContext *C, ARegion *ar, const bool is_set
}
}
- return change;
+ return changed;
}
static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const int xy_input[2])
@@ -768,7 +778,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const
*/
if (drag_info->is_init == false) {
/* first store the buttons original coords */
- uiBut *but = ui_but_find_mouse_over(ar, xy_input[0], xy_input[1]);
+ uiBut *but = ui_but_find_mouse_over_ex(ar, xy_input[0], xy_input[1], true);
if (but) {
if (but->flag & UI_BUT_DRAG_LOCK) {
@@ -839,7 +849,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
if (done) {
wmWindow *win = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
- uiBut *but = ui_but_find_mouse_over(ar, drag_info->xy_init[0], drag_info->xy_init[1]);
+ uiBut *but = ui_but_find_mouse_over_ex(ar, drag_info->xy_init[0], drag_info->xy_init[1], true);
if (but) {
ui_apply_undo(but);
@@ -881,7 +891,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
if (but->imb) {
/* use button size itself */
}
- else if (but->flag & UI_ICON_LEFT) {
+ else if (but->drawflag & UI_BUT_ICON_LEFT) {
rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect));
}
else {
@@ -1541,13 +1551,22 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
char *str;
opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */
- str = WM_operator_pystring_ex(C, NULL, false, but->optype, opptr);
+ str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
WM_clipboard_text_set(str, 0);
MEM_freeN(str);
}
}
+ /* menu (any type) */
+ else if (ELEM(but->type, MENU, PULLDOWN)) {
+ MenuType *mt = uiButGetMenuType(but);
+ if (mt) {
+ char str[32 + sizeof(mt->idname)];
+ BLI_snprintf(str, sizeof(str), "bpy.ops.wm.call_menu(name=\"%s\")", mt->idname);
+ WM_clipboard_text_set(str, 0);
+ }
+ }
}
/* ************************ password text ******************************
@@ -1596,7 +1615,7 @@ void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but
}
else {
/* convert text to hidden test using asterisks (e.g. pass -> ****) */
- int i, len = BLI_strlen_utf8(but->drawstr);
+ const size_t len = BLI_strlen_utf8(but->drawstr);
/* remap cursor positions */
if (but->pos >= 0) {
@@ -1608,9 +1627,8 @@ void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but
/* save original string */
BLI_strncpy(password_str, but->drawstr, UI_MAX_DRAW_STR);
- for (i = 0; i < len; i++)
- but->drawstr[i] = '*';
- but->drawstr[i] = '\0';
+ memset(but->drawstr, '*', len);
+ but->drawstr[len] = '\0';
}
}
@@ -1622,14 +1640,14 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
{
char *str = data->str;
const int len = strlen(str);
- bool change = false;
+ bool changed = false;
if (but->selsta != but->selend && len) {
memmove(str + but->selsta, str + but->selend, (len - but->selend) + 1);
- change = true;
+ changed = true;
}
but->pos = but->selend = but->selsta;
- return change;
+ return changed;
}
/* note, but->block->aspect is used here, when drawing button style is getting scaled too */
@@ -1648,9 +1666,9 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
ui_button_text_password_hide(password_str, but, FALSE);
origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr");
-
+
BLI_strncpy(origstr, but->drawstr, data->maxlen);
-
+
/* XXX solve generic, see: #widget_draw_text_icon */
if (but->type == NUM || but->type == NUMSLI) {
startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect)));
@@ -1672,7 +1690,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
while (i > 0) {
if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) {
/* 0.25 == scale factor for less sensitivity */
- if (BLF_width(fstyle->uifont_id, origstr + i) > (startx - x) * 0.25f) {
+ if (BLF_width(fstyle->uifont_id, origstr + i, BLF_DRAW_STR_DUMMY_MAX) > (startx - x) * 0.25f) {
break;
}
}
@@ -1694,7 +1712,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
but->pos = pos_prev = strlen(origstr) - but->ofs;
while (true) {
- cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs);
+ cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs, BLF_DRAW_STR_DUMMY_MAX);
/* check if position is found */
if (cdist < x) {
@@ -1889,7 +1907,7 @@ static bool ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directi
int step;
BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
step = pos - but->pos;
- memmove(&str[but->pos], &str[but->pos + step], (len + 1) - but->pos);
+ memmove(&str[but->pos], &str[but->pos + step], (len + 1) - (but->pos + step));
changed = true;
}
}
@@ -1914,22 +1932,22 @@ static bool ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directi
return changed;
}
-static bool ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data)
+static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData *data)
{
char *str;
- bool change = true;
+ int changed;
str = data->str;
if (data->searchbox)
- change = ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
+ changed = ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
else
- change = but->autocomplete_func(C, str, but->autofunc_arg);
+ changed = but->autocomplete_func(C, str, but->autofunc_arg);
but->pos = strlen(str);
but->selsta = but->selend = but->pos;
- return change;
+ return changed;
}
/* mode for ui_textedit_copypaste() */
@@ -2097,7 +2115,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, LISTLABEL, SEPR, ROUNDBOX, LISTBOX))
+ if (ELEM4(actbut->type, LABEL, SEPR, ROUNDBOX, LISTBOX))
return;
for (but = actbut->next; but; but = but->next) {
@@ -2125,7 +2143,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, LISTLABEL, SEPR, ROUNDBOX, LISTBOX))
+ if (ELEM4(actbut->type, LABEL, SEPR, ROUNDBOX, LISTBOX))
return;
for (but = actbut->prev; but; but = but->prev) {
@@ -2324,7 +2342,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case TABKEY:
/* there is a key conflict here, we can't tab with autocomplete */
if (but->autocomplete_func || data->searchbox) {
- changed = ui_textedit_autocomplete(C, but, data);
+ int autocomplete = ui_textedit_autocomplete(C, but, data);
+ changed = autocomplete != AUTOCOMPLETE_NO_MATCH;
+
+ if (autocomplete == AUTOCOMPLETE_FULL_MATCH)
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
update = true; /* do live update for tab key */
}
/* the hotkey here is not well defined, was G.qual so we check all */
@@ -2572,6 +2595,26 @@ int ui_button_open_menu_direction(uiBut *but)
return 0;
}
+/* Hack for uiList LISTROW buttons to "give" events to overlaying TEX buttons (cltr-clic rename feature & co). */
+static uiBut *ui_but_list_row_text_activate(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event,
+ uiButtonActivateType activate_type)
+{
+ ARegion *ar = CTX_wm_region(C);
+ uiBut *labelbut = ui_but_find_mouse_over_ex(ar, event->x, event->y, true);
+
+ if (labelbut && labelbut->type == TEX) {
+ /* exit listrow */
+ data->cancel = true;
+ button_activate_exit(C, but, data, false, false);
+
+ /* Activate the text button. */
+ button_activate_init(C, ar, labelbut, activate_type);
+
+ return labelbut;
+ }
+ return NULL;
+}
+
/* ***************** events for different button types *************** */
static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
@@ -3518,22 +3561,45 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return retval;
}
+static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ /* hack to pass on ctrl+click and double click to overlapping text
+ * editing field for editing list item names
+ */
+ if ((ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) ||
+ (event->type == LEFTMOUSE && event->val == KM_DBL_CLICK))
+ {
+ uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
+ if (labelbut) {
+ /* Nothing else to do. */
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+
+ return ui_do_but_EXIT(C, but, data, event);
+}
+
+
static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
uiList *ui_list = but->custom_data;
int *size = (int *)but->poin;
- int mx, my, raw_dir_sign;
+ int mx, my, dragx, dragy;
int retval = WM_UI_HANDLER_CONTINUE;
- mx = event->x;
- my = event->y;
-
- /* We find the direction of the mouse since last time, before converting coordinates into block's space.
- * We'll use it to avoid flickering in case some rows are higher than UI_UNIT_Y.
+ /* Note: Having to store org point in window space and recompute it to block "space" each time
+ * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which
+ * returns different results when the block is inside a panel or not...
+ * See T37739.
*/
- raw_dir_sign = (data->draglasty - my < 0) ? -1 : 1;
- data->draglasty = my;
+ dragx = data->dragstartx;
+ dragy = data->dragstarty;
+ ui_window_to_block(data->region, block, &dragx, &dragy);
+ mx = event->x;
+ my = event->y;
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_NUM_EDITING) {
@@ -3559,52 +3625,40 @@ static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
if (data->draglastvalue > 0 && *size == 0) {
data->draglastvalue = *size;
data->dragstartx = data->dragstarty; /* draglasty already used... */
- data->dragstarty = my;
+ data->dragstarty = event->y;
}
else {
- int delta = data->dragstarty - my;
- /* We only actually do something if the real mousemouve direction matches the "virtual"
- * mousemove direction in current block's space. This avoids flickering when drag-resizing lists with
- * items drawing higher that UI_UNIT_Y.
- */
- if (delta * raw_dir_sign > 0) {
- /* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */
- delta = (int)floorf(((float)delta / (float)UI_UNIT_Y) + 0.5f);
-
- /* If we are not in autosize mode, default behavior... */
- if (*size > 0 && delta != 0) {
- /* This prevents some instability in case some items draw more/less than UI_UNIT_Y height. */
- delta = (delta < -5) ? -5 : (delta > 5) ? 5 : delta;
- /* We can't use ui_numedit_apply()... */
- /* list template will clamp, but we do not want to reach 0 aka autosize mode! */
- *size = max_ii(*size + delta, 1);
-
- /* Used to detect switch to/from autosize mode. */
- data->draglastvalue = *size;
-
- data->dragchange = true;
- data->applied = data->applied_interactive = true;
-
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ED_region_tag_redraw(data->region);
- }
- /* If we are leaving autosize mode (growing dragging), restore to minimal size. */
- else if (delta > 0) {
- /* We can't use ui_numedit_apply()... */
- *size = ui_list->dyn_data->visual_height_min;
+ int newsize = *size;
+ int diff = dragy - my;
- /* Restore real dragstarty value! */
- data->dragstarty = data->dragstartx;
+ diff = (int)floorf(((float)diff / (float)UI_UNIT_Y) + 0.5f);
- /* Used to detect switch to/from autosize mode. */
- data->draglastvalue = *size;
+ /* If we are not in autosize mode, default behavior... */
+ if (*size > 0) {
+ /* list template will clamp, but we do not want to reach 0 aka autosize mode! */
+ newsize = data->dragstartvalue + diff;
+ }
+ /* If we are leaving autosize mode (growing dragging), restore to minimal size. */
+ else if (diff > 0) {
+ /* We can't use ui_numedit_apply()... */
+ newsize = ui_list->dyn_data->visual_height_min;
- data->dragchange = true;
- data->applied = data->applied_interactive = true;
+ /* Restore real dragstarty value! */
+ data->dragstarty = data->dragstartx;
+ }
- ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ED_region_tag_redraw(data->region);
- }
+ /* Used to detect switch to/from autosize mode. */
+ data->draglastvalue = newsize;
+
+ if (newsize != *size) {
+ *size = newsize;
+
+ /* We can't use ui_numedit_apply()... */
+ data->dragchange = true;
+ data->applied = data->applied_interactive = true;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(data->region);
}
}
}
@@ -5536,7 +5590,15 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) {
/* handle copy-paste */
if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS && (event->ctrl || event->oskey)) {
-
+ /* Specific handling for listrows, we try to find their overlapping tex button. */
+ if (but->type == LISTROW) {
+ uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_OVER);
+ if (labelbut) {
+ but = labelbut;
+ data = but->active;
+ }
+ }
+
ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v');
return WM_UI_HANDLER_BREAK;
}
@@ -5673,11 +5735,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case LISTBOX:
retval = ui_do_but_LISTBOX(C, block, but, data, event);
break;
+ case LISTROW:
+ retval = ui_do_but_LISTROW(C, but, data, event);
+ break;
case ROUNDBOX:
case LABEL:
- case LISTLABEL:
case ROW:
- case LISTROW:
case BUT_IMAGE:
case PROGRESSBAR:
case NODESOCKET:
@@ -5745,7 +5808,8 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
/* reset to default (generic function, only use if not handled by switch above) */
/* XXX hardcoded keymap check.... */
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ data = but->active;
+ if (data && data->state == BUTTON_STATE_HIGHLIGHT) {
if ((retval == WM_UI_HANDLER_CONTINUE) &&
(event->type == BACKSPACEKEY && event->val == KM_PRESS))
{
@@ -5884,11 +5948,12 @@ static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
/**
* Can we mouse over the button or is it hidden/disabled/layout.
+ * Note: ctrl is kind of a hack currently, so that non-embossed TEX button behaves as a label when ctrl is not pressed.
*/
-bool ui_is_but_interactive(uiBut *but)
+static bool ui_is_but_interactive(uiBut *but, const bool labeledit)
{
/* note, LABEL is included for highlights, this allows drags */
- if (ELEM(but->type, LABEL, LISTLABEL) && but->dragpoin == NULL)
+ if ((but->type == LABEL) && but->dragpoin == NULL)
return false;
if (ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX))
return false;
@@ -5896,6 +5961,10 @@ bool ui_is_but_interactive(uiBut *but)
return false;
if (but->flag & UI_SCROLLED)
return false;
+ if ((but->type == TEX) && (but->dt & UI_EMBOSSN) && !labeledit)
+ return false;
+ if ((but->type == LISTROW) && labeledit)
+ return false;
return true;
}
@@ -5907,7 +5976,8 @@ bool ui_is_but_search_unlink_visible(uiBut *but)
(but->drawstr[0] != '\0'));
}
-uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+/* x and y are only used in case event is NULL... */
+static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit)
{
uiBlock *block;
uiBut *but, *butover = NULL;
@@ -5924,7 +5994,7 @@ uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
ui_window_to_block(ar, block, &mx, &my);
for (but = block->buttons.first; but; but = but->next) {
- if (ui_is_but_interactive(but)) {
+ if (ui_is_but_interactive(but, labeledit)) {
if (ui_but_contains_pt(but, mx, my)) {
butover = but;
}
@@ -5943,6 +6013,12 @@ uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
return butover;
}
+static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
+{
+ return ui_but_find_mouse_over_ex(ar, event->x, event->y, event->ctrl != 0);
+}
+
+
static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
{
uiBlock *block;
@@ -6494,7 +6570,7 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
uiBut *but;
if (event->type == MOUSEMOVE) {
- but = ui_but_find_mouse_over(ar, event->x, event->y);
+ but = ui_but_find_mouse_over(ar, event);
if (but) {
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
@@ -6586,7 +6662,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
data->cancel = TRUE;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
- else if (ui_but_find_mouse_over(ar, event->x, event->y) != but) {
+ else if (ui_but_find_mouse_over(ar, event) != but) {
data->cancel = TRUE;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -6641,9 +6717,10 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case MOUSEMOVE:
if (ELEM(but->type, LINK, INLINK)) {
+ ARegion *ar = data->region;
but->flag |= UI_SELECT;
ui_do_button(C, block, but, event);
- ED_region_tag_redraw(data->region);
+ ED_region_tag_redraw(ar);
}
else {
/* deselect the button when moving the mouse away */
@@ -6698,7 +6775,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
}
- bt = ui_but_find_mouse_over(ar, event->x, event->y);
+ bt = ui_but_find_mouse_over(ar, event);
if (bt && bt->active != data) {
if (but->type != COLOR) { /* exception */
@@ -6720,7 +6797,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
/* may have been re-allocated above (eyedropper for eg) */
data = but->active;
- if (data->state == BUTTON_STATE_EXIT) {
+ if (data && data->state == BUTTON_STATE_EXIT) {
uiBut *post_but = data->postbut;
uiButtonActivateType post_type = data->posttype;
@@ -6738,7 +6815,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
* it stays active while the mouse is over it.
* This avoids adding mousemoves, see: [#33466] */
if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) {
- if (ui_but_find_mouse_over(ar, event->x, event->y) == but) {
+ if (ui_but_find_mouse_over(ar, event) == but) {
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
}
@@ -6779,7 +6856,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
break;
}
}
- if (dragbut && dragbut == ui_but_find_mouse_over(ar, event->x, event->y)) {
+ if (dragbut && dragbut == ui_but_find_mouse_over(ar, event)) {
is_over_dragbut = true;
}
@@ -6791,12 +6868,13 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
button_activate_state(C, but, BUTTON_STATE_INIT);
data = but->active;
- data->dragstarty = my;
+ data->dragstarty = event->y;
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
/* Again, have to override values set by ui_numedit_begin, because our listbox button also has a rnapoin... */
*size = data->origvalue = (double)dyn_data->visual_height;
+ data->dragstartvalue = *size;
ui_list->flag |= UILST_RESIZING;
retval = WM_UI_HANDLER_BREAK;
@@ -7444,7 +7522,7 @@ static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockH
for (but = block->buttons.first; but; but = but->next) {
int doit = FALSE;
- if (but->type != LABEL && but->type != LISTLABEL && but->type != SEPR)
+ if (!ELEM(but->type, LABEL, SEPR))
count++;
/* exception for rna layer buts */
@@ -7775,7 +7853,7 @@ static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(use
/* either handle events for already activated button or try to activate */
but = ui_but_find_activated(ar);
- retval = ui_handler_panel_region(C, event);
+ retval = ui_handler_panel_region(C, event, ar);
if (retval == WM_UI_HANDLER_CONTINUE)
retval = ui_handle_list_event(C, event, ar);
@@ -7961,8 +8039,8 @@ void UI_remove_popup_handlers_all(bContext *C, ListBase *handlers)
WM_event_free_ui_handler_all(C, handlers, ui_handler_popup, ui_handler_remove_popup);
}
-bool UI_textbutton_activate_event(const bContext *C, ARegion *ar,
- const void *rna_poin_data, const char *rna_prop_id)
+bool UI_textbutton_activate_rna(const bContext *C, ARegion *ar,
+ const void *rna_poin_data, const char *rna_prop_id)
{
uiBlock *block;
uiBut *but = NULL;
@@ -7990,6 +8068,31 @@ bool UI_textbutton_activate_event(const bContext *C, ARegion *ar,
}
}
+bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut)
+{
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ uiBut *but = NULL;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ for (but = block->buttons.first; but; but = but->next)
+ if (but == actbut && but->type == TEX)
+ break;
+
+ if (but)
+ break;
+ }
+
+ if (but) {
+ uiButActiveOnly(C, ar, block, but);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
void ui_button_clipboard_free(void)
{
curvemapping_free_data(&but_copypaste_curve);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 5ecd1e55086..cbc1cd2cbbd 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -54,6 +54,9 @@ struct ImBuf;
/* ****************** general defines ************** */
+#define RNA_NO_INDEX -1
+#define RNA_ENUM_VALUE -2
+
/* visual types for drawing */
/* for time being separated from functional types */
typedef enum {
@@ -95,7 +98,6 @@ typedef enum {
UI_WTYPE_SCROLL,
UI_WTYPE_LISTITEM,
UI_WTYPE_PROGRESSBAR,
- UI_WTYPE_LISTLABEL,
} uiWidgetTypeEnum;
/* menu scrolling */
@@ -108,13 +110,15 @@ typedef enum {
#define UI_PANEL_MINY 70
/* uiBut->flag */
-#define UI_SELECT 1 /* use when the button is pressed */
-#define UI_SCROLLED 2 /* temp hidden, scrolled away */
-#define UI_ACTIVE 4
-#define UI_HAS_ICON 8
-#define UI_TEXTINPUT 16
-#define UI_HIDDEN 32
-/* warn: rest of uiBut->flag in UI_interface.h */
+enum {
+ UI_SELECT = (1 << 0), /* use when the button is pressed */
+ UI_SCROLLED = (1 << 1), /* temp hidden, scrolled away */
+ UI_ACTIVE = (1 << 2),
+ UI_HAS_ICON = (1 << 3),
+ UI_TEXTINPUT = (1 << 4),
+ UI_HIDDEN = (1 << 5),
+ /* warn: rest of uiBut->flag in UI_interface.h */
+};
/* internal panel drawing defines */
#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
@@ -144,6 +148,9 @@ typedef enum {
/* bit-row */
#define UI_BITBUT_ROW(min, max) (((max) >= 31 ? 0xFFFFFFFF : (1 << (max + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0) )
+/* split numbuts by ':' and align l/r */
+#define USE_NUMBUTS_LR_ALIGN
+
typedef struct uiLinkLine { /* only for draw/edit */
struct uiLinkLine *next, *prev;
struct uiBut *from, *to;
@@ -402,7 +409,6 @@ extern bool ui_is_but_bool(uiBut *but);
extern bool ui_is_but_unit(uiBut *but);
extern bool ui_is_but_rna_valid(uiBut *but);
extern bool ui_is_but_utf8(uiBut *but);
-extern bool ui_is_but_interactive(uiBut *but);
extern bool ui_is_but_search_unlink_visible(uiBut *but);
extern int ui_is_but_push_ex(uiBut *but, double *value);
@@ -476,7 +482,7 @@ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBu
bool ui_searchbox_inside(struct ARegion *ar, int x, int y);
int ui_searchbox_find_index(struct ARegion *ar, const char *name);
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, const bool reset);
-bool ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
+int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event);
bool ui_searchbox_apply(uiBut *but, struct ARegion *ar);
void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
@@ -498,23 +504,23 @@ int ui_step_name_menu(uiBut *but, int step);
struct AutoComplete;
/* interface_panel.c */
-extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event);
-extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect);
+extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar);
+extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect);
/* interface_draw.c */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
-void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_COLORBAND(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
-void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
+void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_COLORBAND(uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
/* interface_handlers.c */
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
@@ -559,6 +565,7 @@ int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
+void init_userdef_factory(void);
void ui_theme_init_default(void);
void ui_style_init_default(void);
void ui_resources_init(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 0f6034ba1cd..85068998d9c 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -64,10 +64,6 @@
/************************ Structs and Defines *************************/
-#define RNA_NO_INDEX -1
-#define RNA_ENUM_VALUE -2
-
-
// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now.
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
@@ -390,11 +386,15 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
layer_used = arm->layer_used;
- if (arm->edbo && arm->act_edbone) {
- layer_active |= arm->act_edbone->layer;
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ layer_active |= arm->act_edbone->layer;
+ }
}
- else if (arm->act_bone) {
- layer_active |= arm->act_bone->layer;
+ else {
+ if (arm->act_bone) {
+ layer_active |= arm->act_bone->layer;
+ }
}
}
@@ -580,7 +580,7 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
}
if (ui_layout_local_dir(layout) != UI_LAYOUT_HORIZONTAL)
- but->flag |= UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
}
uiBlockSetCurLayout(block, layout);
@@ -628,13 +628,11 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
if (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
uiBlockSetCurLayout(block, uiLayoutRow(sub, TRUE));
- uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
+ but = uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w - UI_UNIT_X, h);
/* BUTTONS_OT_file_browse calls uiFileBrowseContextProperty */
- but = uiDefIconButO(block, BUT, subtype == PROP_DIRPATH ?
- "BUTTONS_OT_directory_browse" :
- "BUTTONS_OT_file_browse",
- WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
+ uiDefIconButO(block, BUT, subtype == PROP_DIRPATH ? "BUTTONS_OT_directory_browse" : "BUTTONS_OT_file_browse",
+ WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL);
}
else if (flag & UI_ITEM_R_EVENT) {
uiDefButR_prop(block, KEYEVT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL);
@@ -762,7 +760,7 @@ PointerRNA uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *nam
/* text alignment for toolbar buttons */
if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon)
- but->flag |= UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
if (flag & UI_ITEM_R_NO_BG)
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -910,9 +908,15 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
block->flag |= UI_BLOCK_NO_FLIP;
}
- uiItemL(column, item->name, ICON_NONE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
+ if (item->icon) {
+ uiItemL(column, item->name, item->icon);
+ but = block->buttons.last;
+ }
+ else {
+ /* Do not use uiItemL here, as our root layout is a menu one, it will add a fake blank icon! */
+ but = uiDefBut(block, LABEL, 0, item->name, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL,
+ 0.0, 0.0, 0, 0, "");
+ }
ui_but_tip_from_enum_item(but, item);
}
else { /* XXX bug here, colums draw bottom item badly */
@@ -1138,7 +1142,7 @@ static void ui_item_rna_size(uiLayout *layout, const char *name, int icon, Point
void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index, int value, int flag, const char *name, int icon)
{
uiBlock *block = layout->root->block;
- uiBut *but;
+ uiBut *but = NULL;
PropertyType type;
char namestr[UI_MAX_NAME_STR];
int len, is_array, w, h, slider, toggle, expand, icon_only, no_bg;
@@ -1227,7 +1231,12 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
if (layout->redalert)
uiButSetFlag(but, UI_BUT_REDALERT);
}
-
+
+ /* Mark non-embossed textfields inside a listbox. */
+ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == TEX) && (but->dt & UI_EMBOSSN)) {
+ uiButSetFlag(but, UI_BUT_LIST_ITEM);
+ }
+
if (no_bg)
uiBlockSetEmboss(block, UI_EMBOSS);
}
@@ -1336,7 +1345,7 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
uiItemL(column, item[i].name, ICON_NONE);
bt = block->buttons.last;
- bt->flag = UI_TEXT_LEFT;
+ bt->drawflag = UI_BUT_TEXT_LEFT;
ui_but_tip_from_enum_item(bt, &item[i]);
}
@@ -1486,7 +1495,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->hardmax = MAX2(but->hardmax, 256.0f);
but->rnasearchpoin = *searchptr;
but->rnasearchprop = searchprop;
- but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
if (RNA_property_type(prop) == PROP_ENUM) {
/* XXX, this will have a menu string,
@@ -1629,7 +1638,7 @@ static void ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCre
(force_menu && layout->root->type != UI_LAYOUT_MENU)) /* We never want a dropdown in menu! */
{
but->type = MENU;
- but->flag |= UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
}
}
@@ -1681,13 +1690,13 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
* make text aligned right if the layout is aligned right.
*/
if (uiLayoutGetAlignment(layout) == UI_LAYOUT_ALIGN_RIGHT) {
- but->flag &= ~UI_TEXT_LEFT; /* default, needs to be unset */
- but->flag |= UI_TEXT_RIGHT;
+ but->drawflag &= ~UI_BUT_TEXT_LEFT; /* default, needs to be unset */
+ but->drawflag |= UI_BUT_TEXT_RIGHT;
}
/* Mark as a label inside a listbox. */
if (block->flag & UI_BLOCK_LIST_ITEM) {
- but->type = LISTLABEL;
+ but->flag |= UI_BUT_LIST_ITEM;
}
return but;
@@ -1872,7 +1881,7 @@ static int ui_litem_min_width(int itemw)
static void ui_litem_layout_row(uiLayout *litem)
{
uiItem *item;
- int x, y, w, tot, totw, neww, itemw, minw, itemh, offset;
+ int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset;
int fixedw, freew, fixedx, freex, flag = 0, lastw = 0;
/* x = litem->x; */ /* UNUSED */
@@ -1899,6 +1908,7 @@ static void ui_litem_layout_row(uiLayout *litem)
freew = 0;
x = 0;
flag = 0;
+ newtotw = totw;
for (item = litem->items.first; item; item = item->next) {
if (item->flag)
@@ -1919,7 +1929,7 @@ static void ui_litem_layout_row(uiLayout *litem)
item->flag = 1;
fixedw += minw;
flag = 1;
- totw -= itemw;
+ newtotw -= itemw;
}
else {
/* keep free size */
@@ -1928,6 +1938,7 @@ static void ui_litem_layout_row(uiLayout *litem)
}
}
+ totw = newtotw;
lastw = fixedw;
} while (flag);
@@ -2448,8 +2459,9 @@ uiLayout *uiLayoutBox(uiLayout *layout)
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
}
-/* Check all buttons defined in this layout, and set labels as active/selected.
- * Needed to handle correctly text colors of list items. */
+/* Check all buttons defined in this layout, and set any button flagged as UI_BUT_LIST_ITEM as active/selected.
+ * Needed to handle correctly text colors of active (selected) list item.
+ */
void ui_layout_list_set_labels_active(uiLayout *layout)
{
uiButtonItem *bitem;
@@ -2457,7 +2469,7 @@ void ui_layout_list_set_labels_active(uiLayout *layout)
if (bitem->item.type != ITEM_BUTTON) {
ui_layout_list_set_labels_active((uiLayout *)(&bitem->item));
}
- else if (bitem->but->type == LISTLABEL) {
+ else if (bitem->but->flag & UI_BUT_LIST_ITEM) {
uiButSetFlag(bitem->but, UI_SELECT);
}
}
@@ -2965,7 +2977,7 @@ static void ui_intro_button(DynStr *ds, uiButtonItem *bitem)
BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : ""); /* not exactly needed, rna has this */
if (but->optype) {
- char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, but->optype, but->opptr);
+ char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, true, but->optype, but->opptr);
BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
MEM_freeN(opstr);
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 3fe11ad3a6b..9759614dd4c 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -413,7 +413,7 @@ static void ui_draw_x_icon(float x, float y)
#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
-static void ui_draw_panel_scalewidget(rcti *rect)
+static void ui_draw_panel_scalewidget(const rcti *rect)
{
float xmin, xmax, dx;
float ymin, ymax, dy;
@@ -464,7 +464,7 @@ static void ui_draw_panel_dragwidget(const rctf *rect)
}
-static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *rect, char dir)
+static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const rcti *rect, char dir)
{
Panel *panel = block->panel;
rcti hrect;
@@ -496,21 +496,8 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r
}
}
-static void rectf_scale(rctf *rect, const float scale)
-{
- float centx = BLI_rctf_cent_x(rect);
- float centy = BLI_rctf_cent_y(rect);
- float sizex = BLI_rctf_size_x(rect) * 0.5f * scale;
- float sizey = BLI_rctf_size_y(rect) * 0.5f * scale;
-
- rect->xmin = centx - sizex;
- rect->xmax = centx + sizex;
- rect->ymin = centy - sizey;
- rect->ymax = centy + sizey;
-}
-
/* panel integrated in buttonswindow, tool/property lists etc */
-void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
+void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect)
{
Panel *panel = block->panel;
rcti headrect;
@@ -565,7 +552,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
- rectf_scale(&itemrect, 0.7f);
+ BLI_rctf_scale(&itemrect, 0.7f);
ui_draw_panel_dragwidget(&itemrect);
}
@@ -619,7 +606,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
itemrect.ymin = headrect.ymin;
itemrect.ymax = headrect.ymax;
- rectf_scale(&itemrect, 0.35f);
+ BLI_rctf_scale(&itemrect, 0.35f);
if (panel->flag & PNL_CLOSEDY)
ui_draw_tria_rect(&itemrect, 'h');
@@ -1133,16 +1120,15 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
/* XXX should become modal keymap */
/* AKey is opening/closing panels, independent of button state now */
-int ui_handler_panel_region(bContext *C, const wmEvent *event)
+int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
{
- ARegion *ar = CTX_wm_region(C);
uiBlock *block;
Panel *pa;
int retval, mx, my;
retval = WM_UI_HANDLER_CONTINUE;
for (block = ar->uiblocks.last; block; block = block->prev) {
- int inside = 0, inside_header = 0, inside_scale = 0;
+ bool inside = false, inside_header = false, inside_scale = false;
mx = event->x;
my = event->y;
@@ -1159,24 +1145,24 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event)
/* clicked at panel header? */
if (pa->flag & PNL_CLOSEDX) {
if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx)
- inside_header = 1;
+ inside_header = true;
}
else if (block->rect.xmin > mx || block->rect.xmax < mx) {
/* outside left/right side */
}
else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
- inside_header = 1;
+ inside_header = true;
}
else if (!(pa->flag & PNL_CLOSEDY)) {
/* open panel */
if (pa->control & UI_PNL_SCALE) {
if (block->rect.xmax - PNL_HEADER <= mx)
if (block->rect.ymin + PNL_HEADER >= my)
- inside_scale = 1;
+ inside_scale = true;
}
if (block->rect.xmin <= mx && block->rect.xmax >= mx)
if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my)
- inside = 1;
+ inside = true;
}
/* XXX hardcoded key warning */
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 1de0a278b56..167c627c32d 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -443,7 +443,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
- if (but->flag & UI_BUT_NO_TOOLTIP)
+ if (but->drawflag & UI_BUT_NO_TOOLTIP)
return NULL;
/* create tooltip data */
@@ -539,7 +539,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* so the context is passed to itemf functions (some py itemf functions use it) */
WM_operator_properties_sanitize(opptr, false);
- str = WM_operator_pystring_ex(C, NULL, false, but->optype, opptr);
+ str = WM_operator_pystring_ex(C, NULL, false, false, but->optype, opptr);
+
+ /* avoid overly verbose tips (eg, arrays of 20 layers), exact limit is arbitrary */
+ WM_operator_pystring_abbreviate(str, 32);
/* operator info */
if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) {
@@ -660,7 +663,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
h = BLF_height_max(data->fstyle.uifont_id);
for (a = 0, fontw = 0, fonth = 0; a < data->totline; a++) {
- w = BLF_width(data->fstyle.uifont_id, data->lines[a]);
+ w = BLF_width(data->fstyle.uifont_id, data->lines[a], sizeof(data->lines[a]));
fontw = max_ff(fontw, (float)w);
fonth += (a == 0) ? h : h + TIP_MARGIN_Y;
}
@@ -873,7 +876,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
ED_region_tag_redraw(ar);
}
-static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
+static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr)
{
/* thumbnail preview */
if (data->preview) {
@@ -881,27 +884,27 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows;
int row, col;
- *rect = data->bbox;
+ *r_rect = data->bbox;
col = itemnr % data->prv_cols;
row = itemnr / data->prv_cols;
- rect->xmin += col * butw;
- rect->xmax = rect->xmin + butw;
+ r_rect->xmin += col * butw;
+ r_rect->xmax = r_rect->xmin + butw;
- rect->ymax = data->bbox.ymax - MENU_TOP - (row * buth);
- rect->ymin = rect->ymax - buth;
+ r_rect->ymax = data->bbox.ymax - MENU_TOP - (row * buth);
+ r_rect->ymin = r_rect->ymax - buth;
}
/* list view */
else {
int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS;
- *rect = data->bbox;
- rect->xmin = data->bbox.xmin + 3.0f;
- rect->xmax = data->bbox.xmax - 3.0f;
+ *r_rect = data->bbox;
+ r_rect->xmin = data->bbox.xmin + 3.0f;
+ r_rect->xmax = data->bbox.xmax - 3.0f;
- rect->ymax = data->bbox.ymax - MENU_TOP - itemnr * buth;
- rect->ymin = rect->ymax - buth;
+ r_rect->ymax = data->bbox.ymax - MENU_TOP - itemnr * buth;
+ r_rect->ymin = r_rect->ymax - buth;
}
}
@@ -1051,7 +1054,7 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
ED_region_tag_redraw(ar);
}
-bool ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
+int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
{
uiSearchboxData *data = ar->regiondata;
int match = AUTOCOMPLETE_NO_MATCH;
@@ -1064,7 +1067,8 @@ bool ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
match = autocomplete_end(data->items.autocpl, str);
data->items.autocpl = NULL;
}
- return match != AUTOCOMPLETE_NO_MATCH;
+
+ return match;
}
static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
@@ -1389,9 +1393,9 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* widget_roundbox_set has this correction too, keep in sync */
if (but->type != PULLDOWN) {
- if (but->flag & UI_BUT_ALIGN_TOP)
+ if (but->drawflag & UI_BUT_ALIGN_TOP)
butrct.ymax += U.pixelsize;
- if (but->flag & UI_BUT_ALIGN_LEFT)
+ if (but->drawflag & UI_BUT_ALIGN_LEFT)
butrct.xmin -= U.pixelsize;
}
@@ -1791,7 +1795,6 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a
uiBlock *block = uiLayoutGetBlock(layout);
uiPopupBlockHandle *handle = block->handle;
uiLayout *split, *column = NULL;
- uiBut *bt;
MenuData *md;
MenuEntry *entry;
const char *instr = arg_str;
@@ -1800,7 +1803,7 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a
int nbr_entries_nosepr = 0;
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
-
+
/* compute menu data */
md = decompose_menu_string(instr);
@@ -1838,9 +1841,8 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a
uiItemL(layout, md->title, md->titleicon);
}
else {
- uiItemL(layout, md->title, ICON_NONE);
- bt = block->buttons.last;
- bt->flag = UI_TEXT_LEFT;
+ /* Do not use uiItemL here, as our root layout is a menu one, it will add a fake blank icon! */
+ uiDefBut(block, LABEL, 0, md->title, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
}
@@ -1874,9 +1876,13 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a
if (entry->sepr) {
if (entry->str[0]) {
- uiItemL(column, entry->str, entry->icon);
- bt = block->buttons.last;
- bt->flag = UI_TEXT_LEFT;
+ if (entry->icon) {
+ uiItemL(column, entry->str, entry->icon);
+ }
+ else {
+ /* Do not use uiItemL here, as our root layout is a menu one, it will add a fake blank icon! */
+ uiDefBut(block, LABEL, 0, entry->str, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ }
}
else {
uiItemS(column);
@@ -1891,7 +1897,7 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a
UI_UNIT_X * 5, UI_UNIT_X, &handle->retvalue, (float) entry->retval, 0.0, 0, -1, "");
}
}
-
+
menudata_free(md);
}
@@ -2191,11 +2197,11 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
/* RGB values */
uiBlockBeginAlign(block);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("R "), 0, yco, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("R:"), 0, yco, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("G "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("G:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("B "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("B:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
/* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
@@ -2204,11 +2210,11 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
/* HSV values */
yco = -3.0f * UI_UNIT_Y;
uiBlockBeginAlign(block);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("H "), 0, yco, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("H:"), 0, yco, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("S "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("S:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("V "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 2, 0.0, softmax, 10, 3, TIP_("Value"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("V:"), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 2, 0.0, softmax, 10, 3, TIP_("Value"));
bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
uiBlockEndAlign(block);
@@ -2560,7 +2566,7 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
}
else {
but = uiDefBut(pup->block, LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
- but->flag = UI_TEXT_LEFT;
+ but->drawflag = UI_BUT_TEXT_LEFT;
}
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 1c6263c9dd5..f9595edf616 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -144,7 +144,7 @@ static uiFont *uifont_to_blfont(int id)
void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
- float *r_xofs, float *r_yofs)
+ size_t len, float *r_xofs, float *r_yofs)
{
float height;
int xofs = 0, yofs;
@@ -155,14 +155,14 @@ void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
if (fs->align == UI_STYLE_TEXT_CENTER) {
- xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str)));
+ xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
/* don't center text if it chops off the start of the text, 2 gives some margin */
if (xofs < 2) {
xofs = 2;
}
}
else if (fs->align == UI_STYLE_TEXT_RIGHT) {
- xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str) - 0.1f * U.widget_unit;
+ xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len) - 0.1f * U.widget_unit;
}
/* clip is very strict, so we give it some space */
@@ -179,7 +179,7 @@ void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
if (fs->kerning == 1)
BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
- BLF_draw(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw(fs->uifont_id, str, len);
BLF_disable(fs->uifont_id, BLF_CLIPPING);
if (fs->shadow)
BLF_disable(fs->uifont_id, BLF_SHADOW);
@@ -190,15 +190,15 @@ void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
*r_yofs = yofs;
}
-void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, const char *str)
+void uiStyleFontDraw(uiFontStyle *fs, const rcti *rect, const char *str)
{
float xofs, yofs;
uiStyleFontDrawExt(fs, rect, str,
- &xofs, &yofs);
+ BLF_DRAW_STR_DUMMY_MAX, &xofs, &yofs);
}
/* drawn same as above, but at 90 degree angle */
-void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
+void uiStyleFontDrawRotated(uiFontStyle *fs, const rcti *rect, const char *str)
{
float height;
int xofs, yofs;
@@ -215,7 +215,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
/* rotate counter-clockwise for now (assumes left-to-right language)*/
xofs += height;
- yofs = BLF_width(fs->uifont_id, str) + 5;
+ yofs = BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) + 5;
angle = (float)M_PI / 2.0f;
/* translate rect to vertical */
@@ -298,7 +298,7 @@ int UI_GetStringWidth(const char *str)
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
uiStyleFontSet(fstyle);
- width = BLF_width(fstyle->uifont_id, str);
+ width = BLF_width(fstyle->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
if (fstyle->kerning == 1)
BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index ef9b16f5445..ba827285ace 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -443,7 +443,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
but->icon = RNA_struct_ui_icon(type);
/* default dragging of icon for id browse buttons */
uiButSetDragID(but, id);
- uiButSetFlag(but, UI_HAS_ICON | UI_ICON_LEFT);
+ uiButSetFlag(but, UI_HAS_ICON);
+ uiButSetDrawFlag(but, UI_BUT_ICON_LEFT);
}
if ((idfrom && idfrom->lib) || !editable)
@@ -1482,7 +1483,6 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
TIP_("Delete the active position"));
uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
-
/* XXX, todo for later - convert to operator - campbell */
bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Flip colorband"));
@@ -1500,8 +1500,6 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
bt = uiDefBut(block, BUT_COLORBAND, 0, "", xoffs, line2_y, 300, UI_UNIT_Y, coba, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
-
-
if (coba->tot) {
CBData *cbd = coba->data + coba->cur;
@@ -1519,8 +1517,10 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
}
-static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
+static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr,
+ RNAUpdateCb *cb)
{
+ uiLayout *row;
uiBut *bt;
float unit = BLI_rctf_size_x(butr) / 14.0f;
float xs = butr->xmin;
@@ -1537,25 +1537,35 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand
uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
uiBlockEndAlign(block);
- if (coba->tot) {
- CBData *cbd = coba->data + coba->cur;
- PointerRNA ptr;
- RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
- uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
- }
+ row = uiLayoutRow(layout, FALSE);
bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0,
TIP_("Set interpolation between color stops"));
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+ row = uiLayoutRow(layout, FALSE);
+
bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, butr->ymin, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
- uiBlockEndAlign(block);
+ if (coba->tot) {
+ CBData *cbd = coba->data + coba->cur;
+ PointerRNA ptr;
+
+ RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
+ bt = block->buttons.last;
+ uiButSetFunc(bt, colorband_update_cb, bt, coba);
+
+ uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
+ }
}
-static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr,
+static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, const rctf *butr,
int small, RNAUpdateCb *cb)
{
if (small)
@@ -2474,11 +2484,7 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
int UNUSED(index), int UNUSED(flt_flag))
{
- char *namebuf;
- const char *name;
-
- namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
- name = (namebuf) ? namebuf : "";
+ PropertyRNA *nameprop = RNA_struct_name_property(itemptr->type);
/* Simplest one! */
switch (ui_list->layout_type) {
@@ -2488,14 +2494,14 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
case UILST_LAYOUT_DEFAULT:
case UILST_LAYOUT_COMPACT:
default:
- uiItemL(layout, name, icon);
+ if (nameprop) {
+ uiItemFullR(layout, itemptr, nameprop, RNA_NO_INDEX, 0, UI_ITEM_R_NO_BG, "", icon);
+ }
+ else {
+ uiItemL(layout, "", icon);
+ }
break;
}
-
- /* free name */
- if (namebuf) {
- MEM_freeN(namebuf);
- }
}
static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
@@ -2557,7 +2563,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext
dyn_data->items_shown = 0;
/* Implicitly add heading/trailing wildcards if needed. */
- if (len + 3 <= 32) {
+ if (slen + 3 <= sizeof(filter_buff)) {
filter = filter_buff;
}
else {
@@ -2666,8 +2672,11 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma
if (columns == 0)
columns = 9;
- if (ui_list->list_grip >= rows) {
- maxrows = rows = ui_list->list_grip;
+ if (ui_list->list_grip >= (rows - 1) && ui_list->list_grip != 0) {
+ /* Only enable auto-size mode when we have dragged one row away from minimum size.
+ * Avoids to switch too easily to auto-size mode when resizing to minimum size...
+ */
+ maxrows = rows = max_ii(ui_list->list_grip, rows);
}
else {
ui_list->list_grip = 0; /* Reset to auto-size mode. */
@@ -2712,8 +2721,8 @@ static void prepare_list(uiList *ui_list, int len, int activei, int rows, int ma
}
void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
- PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type, int columns)
+ PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname,
+ int rows, int maxrows, int layout_type, int columns)
{
uiListType *ui_list_type;
uiList *ui_list = NULL;
@@ -2939,7 +2948,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+ uiButSetDrawFlag(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, FALSE);
@@ -2949,7 +2958,6 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
org_i, flt_flag);
-
/* If we are "drawing" active item, set all labels as active. */
if (i == activei) {
ui_layout_list_set_labels_active(sub);
@@ -2975,7 +2983,9 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
case UILST_LAYOUT_COMPACT:
row = uiLayoutRow(layout, TRUE);
- if (dataptr->data && prop && dyn_data->items_shown > 0) {
+ if ((dataptr->data && prop) && (dyn_data->items_shown > 0) &&
+ (activei >= 0) && (activei < dyn_data->items_shown))
+ {
PointerRNA *itemptr = &items_ptr[activei].item;
int org_i = items_ptr[activei].org_idx;
@@ -3026,7 +3036,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+ uiButSetDrawFlag(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, FALSE);
@@ -3303,7 +3313,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
ui_abs = uiLayoutAbsolute(layout, FALSE);
block = uiLayoutGetBlock(ui_abs);
- width = BLF_width(style->widget.uifont_id, report->message);
+ width = BLF_width(style->widget.uifont_id, report->message, report->len);
width = min_ii((int)(rti->widthfac * width), width);
width = max_ii(width, 10);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 97dd4f59ff6..9826f07e464 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -118,7 +118,7 @@ typedef struct uiWidgetType {
void (*state)(struct uiWidgetType *, int state);
void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
- void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
+ void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
} uiWidgetType;
@@ -606,7 +606,7 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
/* prepares shade colors */
-static void shadecolors4(char coltop[4], char *coldown, const char *color, short shadetop, short shadedown)
+static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
{
coltop[0] = CLAMPIS(color[0] + shadetop, 0, 255);
@@ -682,17 +682,14 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
/* light checkers */
glEnable(GL_POLYGON_STIPPLE);
glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255);
glPolygonStipple(checker_stipple_sml);
- glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_POLYGON_STIPPLE);
@@ -700,7 +697,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4ubv((unsigned char *)wcol->inner);
- glEnableClientState(GL_VERTEX_ARRAY);
for (a = 0; a < wtb->totvert; a++) {
x_mid += wtb->inner_v[a][0];
@@ -709,7 +705,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
/* 1/2 solid color */
glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
@@ -719,7 +714,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
inner_v_half[a][1] = wtb->inner_v[a][1];
}
- glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
glDisableClientState(GL_VERTEX_ARRAY);
@@ -882,7 +876,7 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, const rcti
}
/* extra feature allows more alpha blending */
- if (ELEM(but->type, LABEL, LISTLABEL) && but->a1 == 1.0f)
+ if ((but->type == LABEL) && but->a1 == 1.0f)
alpha *= but->a2;
glEnable(GL_BLEND);
@@ -890,7 +884,7 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, const rcti
if (icon && icon != ICON_BLANK1) {
float ofs = 1.0f / aspect;
- if (but->flag & UI_ICON_LEFT) {
+ if (but->drawflag & UI_BUT_ICON_LEFT) {
if (but->block->flag & UI_BLOCK_LOOP) {
if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK))
xs = rect->xmin + 4.0f * ofs;
@@ -956,7 +950,7 @@ static void ui_text_clip_give_next_off(uiBut *but)
*/
static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
+ int border = (but->drawflag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = BLI_rcti_size_x(rect) - border;
if (but->flag & UI_HAS_ICON)
@@ -973,11 +967,11 @@ static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
but->ofs = 0;
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
while (but->strwidth > okwidth) {
ui_text_clip_give_next_off(but);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
@@ -991,7 +985,7 @@ static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
*/
static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
+ int border = (but->drawflag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE;
@@ -1007,20 +1001,16 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rec
if (but->ofs > but->pos)
but->ofs = but->pos;
- if (BLF_width(fstyle->uifont_id, but->drawstr) <= okwidth)
+ if (BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr)) <= okwidth)
but->ofs = 0;
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
while (but->strwidth > okwidth) {
float width;
- char buf[UI_MAX_DRAW_STR];
- /* copy draw string */
- BLI_strncpy_utf8(buf, but->drawstr, sizeof(buf));
/* string position of cursor */
- buf[but->pos] = 0;
- width = BLF_width(fstyle->uifont_id, buf + but->ofs);
+ width = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, but->pos - but->ofs);
/* if cursor is at 20 pixels of right side button we clip left */
if (width > okwidth - 20) {
@@ -1038,7 +1028,7 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rec
but->drawstr[len - bytes] = 0;
}
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
@@ -1055,7 +1045,7 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rec
*/
static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
- int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
+ int border = (but->drawflag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = max_ii(BLI_rcti_size_x(rect) - border, 0);
char *cpoin = NULL;
int drawstr_len = strlen(but->drawstr);
@@ -1067,7 +1057,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
if (fstyle->kerning == 1) /* for BLF_width */
BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr, sizeof(but->drawstr));
but->ofs = 0;
@@ -1095,7 +1085,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
drawstr_len -= bytes;
// BLI_assert(strlen(but->drawstr) == drawstr_len);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
@@ -1103,7 +1093,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
/* after the leading text is gone, chop off the : and following space, with ofs */
while ((but->strwidth > okwidth) && (but->ofs < 2)) {
ui_text_clip_give_next_off(but);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
@@ -1121,7 +1111,7 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
but->drawstr[drawstr_len] = 0;
// BLI_assert(strlen(but->drawstr) == drawstr_len);
- but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
+ but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, sizeof(but->drawstr) - but->ofs);
if (but->strwidth < 10) break;
}
@@ -1132,17 +1122,18 @@ static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti
static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
- //int transopts; // UNUSED
- char *cpoin = NULL;
+ int drawstr_left_len = UI_MAX_DRAW_STR;
+ char *drawstr_right = NULL;
+ bool use_right_only = false;
/* for underline drawing */
float font_xofs, font_yofs;
uiStyleFontSet(fstyle);
- if (but->editstr || (but->flag & UI_TEXT_LEFT))
+ if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT))
fstyle->align = UI_STYLE_TEXT_LEFT;
- else if (but->flag & UI_TEXT_RIGHT)
+ else if (but->drawflag & UI_BUT_TEXT_RIGHT)
fstyle->align = UI_STYLE_TEXT_RIGHT;
else
fstyle->align = UI_STYLE_TEXT_CENTER;
@@ -1152,7 +1143,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* text button selection and cursor */
if (but->editstr && but->pos != -1) {
- short t = 0, pos = 0, ch;
+ short t = 0, pos = 0;
short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
if ((but->selend - but->selsta) > 0) {
@@ -1163,23 +1154,13 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
if (but->drawstr[0] != 0) {
if (but->selsta >= but->ofs) {
- ch = but->drawstr[selsta_tmp];
- but->drawstr[selsta_tmp] = 0;
-
- selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
-
- but->drawstr[selsta_tmp] = ch;
+ selsta_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, selsta_tmp - but->ofs);
}
else {
selsta_draw = 0;
}
-
- ch = but->drawstr[selend_tmp];
- but->drawstr[selend_tmp] = 0;
-
- selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs);
-
- but->drawstr[selend_tmp] = ch;
+
+ selwidth_draw = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, selend_tmp - but->ofs);
glColor4ubv((unsigned char *)wcol->item);
glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2);
@@ -1190,12 +1171,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
pos = but->pos;
if (pos >= but->ofs) {
if (but->drawstr[0] != 0) {
- ch = but->drawstr[pos];
- but->drawstr[pos] = 0;
-
- t = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs) / but->aspect;
-
- but->drawstr[pos] = ch;
+ t = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs, pos - but->ofs) / but->aspect;
}
glColor3f(0.20, 0.6, 0.9);
@@ -1215,20 +1191,45 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* cut string in 2 parts - only for menu entries */
if ((but->block->flag & UI_BLOCK_LOOP)) {
if (ELEM3(but->type, NUM, TEX, NUMSLI) == 0) {
- cpoin = strchr(but->drawstr, UI_SEP_CHAR);
- if (cpoin) *cpoin = 0;
+ drawstr_right = strchr(but->drawstr, UI_SEP_CHAR);
+ if (drawstr_right) {
+ drawstr_left_len = (drawstr_right - but->drawstr);
+ drawstr_right++;
+ }
}
}
+#ifdef USE_NUMBUTS_LR_ALIGN
+ if (!drawstr_right && ELEM(but->type, NUM, NUMSLI) && (but->editstr == NULL)) {
+ drawstr_right = strchr(but->drawstr + but->ofs, ':');
+ if (drawstr_right) {
+ drawstr_right++;
+ drawstr_left_len = (drawstr_right - but->drawstr);
+
+ while (*drawstr_right == ' ') {
+ drawstr_right++;
+ }
+ }
+ else {
+ /* no prefix, even so use only cpoin */
+ drawstr_right = but->drawstr + but->ofs;
+ use_right_only = true;
+ }
+ }
+#endif
+
glColor4ubv((unsigned char *)wcol->text);
- uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs);
+ if (!use_right_only) {
+ uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs,
+ drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
+ }
if (but->menu_key != '\0') {
char fixedbuf[128];
char *str;
- BLI_strncpy(fixedbuf, but->drawstr + but->ofs, sizeof(fixedbuf));
+ BLI_strncpy(fixedbuf, but->drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len));
str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
if (str == NULL)
@@ -1245,7 +1246,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
fixedbuf[ul_index] = '\0';
- ul_advance = BLF_width(fstyle->uifont_id, fixedbuf);
+ ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
BLF_draw(fstyle->uifont_id, "_", 2);
@@ -1257,11 +1258,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
/* part text right aligned */
- if (cpoin) {
+ if (drawstr_right) {
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= ui_but_draw_menu_icon(but) ? UI_DPI_ICON_SIZE : 0.25f * U.widget_unit;
- uiStyleFontDraw(fstyle, rect, cpoin + 1);
- *cpoin = UI_SEP_CHAR;
+ uiStyleFontDraw(fstyle, rect, drawstr_right);
}
}
@@ -1310,17 +1310,17 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* icons default draw 0.8f x height */
rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
- if (but->editstr || (but->flag & UI_TEXT_LEFT)) {
+ if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
- else if ((but->flag & UI_TEXT_RIGHT)) {
+ else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
}
- else if ((but->flag & UI_TEXT_LEFT)) {
+ else if ((but->drawflag & UI_BUT_TEXT_LEFT)) {
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
- else if ((but->flag & UI_TEXT_RIGHT)) {
+ else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
@@ -1656,8 +1656,14 @@ static void widget_state(uiWidgetType *wt, int state)
{
uiWidgetStateColors *wcol_state = wt->wcol_state;
+ if ((state & UI_BUT_LIST_ITEM) && !(state & UI_TEXTINPUT)) {
+ /* Override default widget's colors. */
+ bTheme *btheme = UI_GetTheme();
+ wt->wcol_theme = &btheme->tui.wcol_list_item;
+ }
+
wt->wcol = *(wt->wcol_theme);
-
+
if (state & UI_SELECT) {
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
@@ -2289,7 +2295,7 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
{
uiWidgetBase wtb;
const float rad = 0.5f * BLI_rcti_size_y(rect);
- float textofs = rad * 0.75f;
+ float textofs = rad * 0.85f;
if (state & UI_SELECT)
SWAP(short, wcol->shadetop, wcol->shadedown);
@@ -2318,9 +2324,9 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round
widget_numbut_draw(wcol, rect, state, roundboxalign, false);
}
-/*
+/**
* Draw number buttons still with triangles when field is not embossed
-*/
+ */
static void widget_numbut_embossn(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
widget_numbut_draw(wcol, rect, state, roundboxalign, true);
@@ -2335,7 +2341,7 @@ int ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
vec[3][0] = rect->xmax;
vec[3][1] = rect->ymax;
- dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
+ dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
vec[1][0] = vec[0][0] + dist;
vec[1][1] = vec[0][1];
@@ -2866,12 +2872,21 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
/* labels use Editor theme colors for text */
static void widget_state_label(uiWidgetType *wt, int state)
{
- /* call this for option button */
- widget_state(wt, state);
- if (state & UI_SELECT)
- UI_GetThemeColor3ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
- else
- UI_GetThemeColor3ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
+ if (state & UI_BUT_LIST_ITEM) {
+ /* Override default label theme's colors. */
+ bTheme *btheme = UI_GetTheme();
+ wt->wcol_theme = &btheme->tui.wcol_list_item;
+ /* call this for option button */
+ widget_state(wt, state);
+ }
+ else {
+ /* call this for option button */
+ widget_state(wt, state);
+ if (state & UI_SELECT)
+ UI_GetThemeColor3ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
+ else
+ UI_GetThemeColor3ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
+ }
}
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
@@ -2991,11 +3006,6 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_REGULAR:
break;
- case UI_WTYPE_LISTLABEL:
- wt.wcol_theme = &btheme->tui.wcol_list_item;
- wt.draw = NULL;
- /* Can't use usual label code. */
- break;
case UI_WTYPE_LABEL:
wt.draw = NULL;
wt.state = widget_state_label;
@@ -3139,15 +3149,15 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
int roundbox = UI_CNR_ALL;
/* alignment */
- if ((but->flag & UI_BUT_ALIGN) && but->type != PULLDOWN) {
+ if ((but->drawflag & UI_BUT_ALIGN) && but->type != PULLDOWN) {
/* ui_block_position has this correction too, keep in sync */
- if (but->flag & UI_BUT_ALIGN_TOP)
+ if (but->drawflag & UI_BUT_ALIGN_TOP)
rect->ymax += U.pixelsize;
- if (but->flag & UI_BUT_ALIGN_LEFT)
+ if (but->drawflag & UI_BUT_ALIGN_LEFT)
rect->xmin -= U.pixelsize;
- switch (but->flag & UI_BUT_ALIGN) {
+ switch (but->drawflag & UI_BUT_ALIGN) {
case UI_BUT_ALIGN_TOP:
roundbox = UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT;
break;
@@ -3245,11 +3255,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
fstyle = &style->widgetlabel;
}
break;
-
- case LISTLABEL:
- wt = widget_type(UI_WTYPE_LISTLABEL);
- fstyle = &style->widgetlabel;
- break;
case SEPR:
break;
@@ -3295,7 +3300,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case OPTIONN:
if (!(but->flag & UI_HAS_ICON)) {
wt = widget_type(UI_WTYPE_OPTION);
- but->flag |= UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
}
else
wt = widget_type(UI_WTYPE_TOGGLE);
@@ -3529,7 +3534,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
cpoin = strchr(name, UI_SEP_CHAR);
if (cpoin) {
*cpoin = 0;
- rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
+ rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + 10;
}
}
@@ -3575,7 +3580,7 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
widget_draw_preview(iconid, 1.0f, rect);
- BLF_width_and_height(fstyle->uifont_id, name, &font_dims[0], &font_dims[1]);
+ BLF_width_and_height(fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
/* text rect */
trect.xmin += 0;
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 55b353b1031..21176c9a25b 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -389,10 +389,26 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_NODE:
cp = ts->syntaxl; break;
- case TH_NODE_IN_OUT:
+ case TH_NODE_INPUT:
cp = ts->syntaxn; break;
- case TH_NODE_OPERATOR:
+ case TH_NODE_OUTPUT:
+ cp = ts->nodeclass_output; break;
+ case TH_NODE_COLOR:
cp = ts->syntaxb; break;
+ case TH_NODE_FILTER:
+ cp = ts->nodeclass_filter; break;
+ case TH_NODE_VECTOR:
+ cp = ts->nodeclass_vector; break;
+ case TH_NODE_TEXTURE:
+ cp = ts->nodeclass_texture; break;
+ case TH_NODE_PATTERN:
+ cp = ts->nodeclass_pattern; break;
+ case TH_NODE_SCRIPT:
+ cp = ts->nodeclass_script; break;
+ case TH_NODE_LAYOUT:
+ cp = ts->nodeclass_layout; break;
+ case TH_NODE_SHADER:
+ cp = ts->nodeclass_shader; break;
case TH_NODE_CONVERTOR:
cp = ts->syntaxv; break;
case TH_NODE_GROUP:
@@ -913,6 +929,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tima.back, 53, 53, 53, 255);
rgba_char_args_set(btheme->tima.vertex, 0, 0, 0, 255);
rgba_char_args_set(btheme->tima.vertex_select, 255, 133, 0, 255);
+ rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
+ rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
btheme->tima.vertex_size = 3;
btheme->tima.facedot_size = 3;
rgba_char_args_set(btheme->tima.face, 255, 255, 255, 10);
@@ -981,10 +999,18 @@ void ui_theme_init_default(void)
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
- rgba_char_args_set(btheme->tnode.syntaxn, 100, 100, 100, 255); /* in/output */
+ rgba_char_args_set(btheme->tnode.syntaxn, 100, 100, 100, 255); /* in */
+ rgba_char_args_set(btheme->tnode.nodeclass_output, 100, 100, 100, 255); /* output */
rgba_char_args_set(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */
rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
+ rgba_char_args_set(btheme->tnode.nodeclass_texture, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_shader, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_filter, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_script, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_pattern, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_vector, 108, 105, 111, 255); /* operator */
+ rgba_char_args_set(btheme->tnode.nodeclass_layout, 108, 105, 111, 255); /* operator */
rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
rgba_char_args_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */
rgba_char_args_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
@@ -2218,13 +2244,43 @@ void init_userdef_do_versions(void)
/* NOTE!! from now on use U.versionfile and U.subversionfile */
- if (U.versionfile < 269 || (U.versionfile == 268 && U.subversionfile < 3)) {
+ if (U.versionfile < 268 || (U.versionfile == 268 && U.subversionfile < 3)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
}
}
+
+ if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 5)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set(btheme->tima.wire_edit, 192, 192, 192, 255);
+ rgba_char_args_set(btheme->tima.edge_select, 255, 133, 0, 255);
+ }
+ }
+
+ if (U.versionfile < 269 || (U.versionfile == 269 && U.subversionfile < 6)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ char r, g, b;
+ r = btheme->tnode.syntaxn[0];
+ g = btheme->tnode.syntaxn[1];
+ b = btheme->tnode.syntaxn[2];
+ rgba_char_args_test_set(btheme->tnode.nodeclass_output, r, g, b, 255);
+ r = btheme->tnode.syntaxb[0];
+ g = btheme->tnode.syntaxb[1];
+ b = btheme->tnode.syntaxb[2];
+ rgba_char_args_test_set(btheme->tnode.nodeclass_filter, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_vector, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_texture, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_shader, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_script, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_pattern, r, g, b, 255);
+ rgba_char_args_test_set(btheme->tnode.nodeclass_layout, r, g, b, 255);
+ }
+
+ }
if (U.versionfile < 270) {
/* grease pencil - new layer color */
@@ -2246,3 +2302,23 @@ void init_userdef_do_versions(void)
// XXX reset_autosave();
}
+
+/**
+ * Override values in in-memory startup.blend, avoids resaving for small changes.
+ */
+void init_userdef_factory(void)
+{
+ /* defaults from T37518 */
+ U.uiflag2 |= USER_REGION_OVERLAP;
+
+ U.uiflag |= USER_AUTOPERSP;
+ U.uiflag |= USER_ORBIT_SELECTION;
+ U.uiflag |= USER_ZBUF_CURSOR;
+ U.uiflag |= USER_QUIT_PROMPT;
+ U.uiflag |= USER_CONTINUOUS_MOUSE;
+
+ U.ogl_multisamples = USER_MULTISAMPLE_4;
+
+ U.versions = 1;
+ U.savetime = 2;
+}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 037fa7c6a94..39583551bec 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -174,7 +174,7 @@ static void view2d_masks(View2D *v2d, int check_scrollers)
*/
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
- short tot_changed = 0, do_init;
+ bool tot_changed = false, do_init;
uiStyle *style = UI_GetStyle();
do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
@@ -937,11 +937,11 @@ void UI_view2d_totRect_set(View2D *v2d, int width, int height)
}
-int UI_view2d_tab_set(View2D *v2d, int tab)
+bool UI_view2d_tab_set(View2D *v2d, int tab)
{
float default_offset[2] = {0.0f, 0.0f};
float *offset, *new_offset;
- int changed = 0;
+ bool changed = false;
/* if tab changed, change offset */
if (tab != v2d->tab_cur && v2d->tab_offset) {
@@ -958,7 +958,7 @@ int UI_view2d_tab_set(View2D *v2d, int tab)
/* validation should happen in subsequent totRect_set */
- changed = 1;
+ changed = true;
}
/* resize array if needed */
@@ -2172,7 +2172,7 @@ void UI_view2d_text_cache_add(View2D *v2d, float x, float y, const char *str, co
}
/* no clip (yet) */
-void UI_view2d_text_cache_rectf(View2D *v2d, rctf *rect, const char *str, const char col[4])
+void UI_view2d_text_cache_rectf(View2D *v2d, const rctf *rect, const char *str, const char col[4])
{
int len = strlen(str) + 1;
View2DString *v2s = MEM_callocN(sizeof(View2DString) + len, "View2DString");
@@ -2196,7 +2196,7 @@ void UI_view2d_text_cache_draw(ARegion *ar)
int col_pack_prev = 0;
/* investigate using BLF_ascender() */
- const float default_height = strings.first ? BLF_height_default("28") : 0.0f;
+ const float default_height = strings.first ? BLF_height_default("28", 3) : 0.0f;
// glMatrixMode(GL_PROJECTION);
// glPushMatrix();
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index c5c9b1c8ce4..ce6f77afaac 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1288,10 +1288,10 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar,
}
if (smooth_viewtx && fac > FLT_EPSILON) {
- int changed = FALSE;
+ bool changed = false;
if (BLI_rctf_compare(&sms.new_cur, &v2d->cur, FLT_EPSILON) == FALSE)
- changed = TRUE;
+ changed = true;
/* The new view is different from the old one
* so animate the view */
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
index 707622fa841..20d49e89771 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -207,21 +207,26 @@ void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max,
/* Frame Editing Tools */
/* Delete selected frames */
-void ED_masklayer_frames_delete(MaskLayer *masklay)
+bool ED_masklayer_frames_delete(MaskLayer *masklay)
{
MaskLayerShape *masklay_shape, *masklay_shape_next;
+ bool changed = false;
/* error checking */
if (masklay == NULL)
- return;
+ return false;
/* check for frames to delete */
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
masklay_shape_next = masklay_shape->next;
- if (masklay_shape->flag & MASK_SHAPE_SELECT)
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+ changed = true;
+ }
}
+
+ return changed;
}
/* Duplicate selected frames from given mask-layer */
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 5ca0d133b0e..7d7960d2e86 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -38,6 +38,7 @@
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mask.h"
+#include "BKE_report.h"
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -942,11 +943,12 @@ static void delete_feather_points(MaskSplinePoint *point)
}
}
-static int delete_exec(bContext *C, wmOperator *UNUSED(op))
+static int delete_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
+ int num_deleted = 0;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
@@ -972,7 +974,6 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
}
if (count == 0) {
-
/* delete the whole spline */
BLI_remlink(&masklay->splines, spline);
BKE_mask_spline_free(spline);
@@ -983,6 +984,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
}
BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
+
+ num_deleted++;
}
else {
MaskSplinePoint *new_points;
@@ -1010,6 +1013,8 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
spline->tot_point--;
BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
+
+ num_deleted++;
}
}
@@ -1031,11 +1036,16 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ if (num_deleted == 0)
+ return OPERATOR_CANCELLED;
+
/* TODO: only update edited splines */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d control points from mask '%s'", num_deleted, mask->id.name);
+
return OPERATOR_FINISHED;
}
@@ -1047,7 +1057,6 @@ void MASK_OT_delete(wmOperatorType *ot)
ot->idname = "MASK_OT_delete";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = delete_exec;
ot->poll = ED_maskedit_mask_poll;
@@ -1062,12 +1071,12 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
/* do actual selection */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
- int change_layer = FALSE;
+ bool changed_layer = false;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
@@ -1076,19 +1085,19 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
for (spline = masklay->splines.first; spline; spline = spline->next) {
if (ED_mask_spline_select_check(spline)) {
BKE_mask_spline_direction_switch(masklay, spline);
- change = TRUE;
- change_layer = TRUE;
+ changed = true;
+ changed_layer = true;
}
}
- if (change_layer) {
+ if (changed_layer) {
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(masklay, CFRA);
}
}
}
- if (change) {
+ if (changed) {
/* TODO: only update this spline */
BKE_mask_update_display(mask, CFRA);
@@ -1125,12 +1134,12 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op)
MaskLayer *masklay;
int i;
- int change = FALSE;
+ bool changed = false;
/* do actual selection */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
- int change_layer = FALSE;
+ bool changed_layer = false;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
@@ -1142,20 +1151,20 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op)
if (MASKPOINT_ISSEL_ANY(point)) {
BKE_mask_calc_handle_point_auto(spline, point, FALSE);
- change = TRUE;
- change_layer = TRUE;
+ changed = true;
+ changed_layer = true;
}
}
}
- if (change_layer) {
+ if (changed_layer) {
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(masklay, CFRA);
}
}
}
- if (change) {
+ if (changed) {
/* TODO: only update this spline */
BKE_mask_update_display(mask, CFRA);
@@ -1193,7 +1202,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
MaskLayer *masklay;
int handle_type = RNA_enum_get(op->ptr, "type");
- bool change = false;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
@@ -1211,13 +1220,13 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
BezTriple *bezt = &point->bezt;
bezt->h1 = bezt->h2 = handle_type;
- change = true;
+ changed = true;
}
}
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DAG_id_tag_update(&mask->id, 0);
@@ -1258,14 +1267,14 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int changed = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
if (masklay->restrictflag & OB_RESTRICT_VIEW) {
ED_mask_layer_select_set(masklay, TRUE);
masklay->restrictflag &= ~OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
}
}
@@ -1301,7 +1310,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
const int unselected = RNA_boolean_get(op->ptr, "unselected");
- int changed = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@@ -1314,7 +1323,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
ED_mask_layer_select_set(masklay, FALSE);
masklay->restrictflag |= OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
}
@@ -1323,7 +1332,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
else {
if (!ED_mask_layer_select_check(masklay)) {
masklay->restrictflag |= OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
}
@@ -1365,7 +1374,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int changed = FALSE;
+ bool changed = false;
int i;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@@ -1382,7 +1391,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
if (MASKPOINT_ISSEL_ANY(point)) {
BezTriple *bezt = &point->bezt;
bezt->weight = 0.0f;
- changed = TRUE;
+ changed = true;
}
}
}
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 90796e9eb93..613168e43a6 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -412,7 +412,8 @@ static int border_select_exec(bContext *C, wmOperator *op)
rcti rect;
rctf rectf;
- int change = FALSE, mode, extend;
+ int mode;
+ bool changed = false, extend;
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
@@ -450,12 +451,12 @@ static int border_select_exec(bContext *C, wmOperator *op)
BKE_mask_point_select_set_handle(point, FALSE);
}
- change = TRUE;
+ changed = true;
}
}
}
- if (change) {
+ if (changed) {
ED_mask_select_flush_all(mask);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
@@ -486,7 +487,7 @@ void MASK_OT_select_border(wmOperatorType *ot)
WM_operator_properties_gesture_border(ot, TRUE);
}
-static int do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, short select)
+static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, short select)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -496,7 +497,7 @@ static int do_lasso_select_mask(bContext *C, const int mcords[][2], short moves,
int i;
rcti rect;
- int change = FALSE;
+ bool changed = false;
/* get rectangle from operator */
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -533,18 +534,18 @@ static int do_lasso_select_mask(bContext *C, const int mcords[][2], short moves,
BKE_mask_point_select_set_handle(point, select);
}
- change = TRUE;
+ changed = true;
}
}
}
- if (change) {
+ if (changed) {
ED_mask_select_flush_all(mask);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
}
- return change;
+ return changed;
}
static int clip_lasso_select_exec(bContext *C, wmOperator *op)
@@ -610,8 +611,9 @@ static int circle_select_exec(bContext *C, wmOperator *op)
MaskLayer *masklay;
int i;
- int x, y, radius, width, height, mode, change = FALSE;
float zoomx, zoomy, offset[2], ellipse[2];
+ int x, y, radius, width, height, mode;
+ bool changed = false;
/* get operator properties */
x = RNA_int_get(op->ptr, "x");
@@ -649,13 +651,13 @@ static int circle_select_exec(bContext *C, wmOperator *op)
BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT);
BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT);
- change = TRUE;
+ changed = true;
}
}
}
}
- if (change) {
+ if (changed) {
ED_mask_select_flush_all(mask);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
@@ -703,7 +705,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
int is_handle = 0;
const float threshold = 19;
- int change = FALSE;
+ bool changed = false;
ED_mask_mouse_pos(sa, ar, event->mval, co);
@@ -714,10 +716,10 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
masklay->act_spline = spline;
masklay->act_point = point;
- change = TRUE;
+ changed = true;
}
- if (change) {
+ if (changed) {
ED_mask_select_flush_all(mask);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
@@ -750,7 +752,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
/* do actual selection */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@@ -763,12 +765,12 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
for (spline = masklay->splines.first; spline; spline = spline->next) {
if (ED_mask_spline_select_check(spline)) {
ED_mask_spline_select_set(spline, TRUE);
- change = TRUE;
+ changed = true;
}
}
}
- if (change) {
+ if (changed) {
ED_mask_select_flush_all(mask);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 78dba382520..cea350219c0 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -60,7 +60,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
const int frame = CFRA;
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskLayerShape *masklay_shape;
@@ -71,10 +71,10 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
masklay_shape = BKE_mask_layer_shape_verify_frame(masklay, frame);
BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
- change = TRUE;
+ changed = true;
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DAG_id_tag_update(&mask->id, 0);
@@ -106,7 +106,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
const int frame = CFRA;
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskLayerShape *masklay_shape;
@@ -119,11 +119,11 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
if (masklay_shape) {
BKE_mask_layer_shape_unlink(masklay, masklay_shape);
- change = TRUE;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DAG_id_tag_update(&mask->id, OB_RECALC_DATA);
@@ -155,7 +155,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
const int frame = CFRA;
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@@ -208,14 +208,14 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
// printf("%s: skipping\n", __func__);
}
- change = TRUE;
+ changed = true;
}
BKE_mask_layer_shape_free(masklay_shape_reset);
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DAG_id_tag_update(&mask->id, 0);
@@ -255,7 +255,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
const int frame = CFRA;
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
const short do_feather = RNA_boolean_get(op->ptr, "feather");
const short do_location = RNA_boolean_get(op->ptr, "location");
@@ -371,7 +371,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
BKE_mask_layer_shape_free(masklay_shape_tmp);
}
- change = TRUE;
+ changed = true;
}
}
@@ -380,7 +380,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DAG_id_tag_update(&mask->id, 0);
@@ -421,23 +421,23 @@ void ED_mask_layer_shape_auto_key(MaskLayer *masklay, const int frame)
BKE_mask_layer_shape_from_mask(masklay, masklay_shape);
}
-int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame)
+bool ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame)
{
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
ED_mask_layer_shape_auto_key(masklay, frame);
- change = TRUE;
+ changed = true;
}
- return change;
+ return changed;
}
-int ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
+bool ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
{
MaskLayer *masklay;
- int change = FALSE;
+ bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
@@ -446,8 +446,8 @@ int ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
}
ED_mask_layer_shape_auto_key(masklay, frame);
- change = TRUE;
+ changed = true;
}
- return change;
+ return changed;
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 47b9d5e2a9e..f81eef7ac88 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -411,8 +411,8 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "x_subdivisions", 10, 3, INT_MAX, "X Subdivisions", "", 3, 1000);
- RNA_def_int(ot->srna, "y_subdivisions", 10, 3, INT_MAX, "Y Subdivisions", "", 3, 1000);
+ RNA_def_int(ot->srna, "x_subdivisions", 10, 2, INT_MAX, "X Subdivisions", "", 2, 1000);
+ RNA_def_int(ot->srna, "y_subdivisions", 10, 2, INT_MAX, "Y Subdivisions", "", 2, 1000);
ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 7bc3ff3ab77..c3c4bda4178 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -36,6 +36,7 @@
#include "BKE_global.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_report.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -110,8 +111,15 @@ static bool mesh_bisect_interactive_calc(
static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
int ret;
+ if (em->bm->totedgesel == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selected edges/faces required");
+ return OPERATOR_CANCELLED;
+ }
+
/* if the properties are set or there is no rv3d,
* skip model and exec immediately */
@@ -129,8 +137,6 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmGesture *gesture = op->customdata;
BisectData *opdata;
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
opdata->mesh_backup = EDBM_redo_state_store(em);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 6b99f53a5b8..102bad26e28 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -50,6 +50,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
+#include "BKE_report.h"
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
@@ -1075,7 +1076,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
* In such a case we should have gotten hits on edges or verts of the face. */
static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
const float s[2],
- const float v1[2], const float v2[2],
+ const float v1[3], const float v2[3],
BMFace *f,
const float face_tol,
float intersectp[3])
@@ -2646,6 +2647,15 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
KnifeTool_OpData *kcd;
+ if (only_select) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totfacesel == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selected faces required");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
view3d_operator_needs_opengl(C);
/* alloc new customdata */
@@ -2903,17 +2913,16 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
*/
static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
{
- int tottri = f->len - 2;
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- int (*index)[3] = BLI_array_alloca(index, tottri);
+ 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;
float const *best_co[3] = {NULL};
float best_area = -1.0f;
bool ok = false;
- tottri = BM_face_calc_tessellation(f, loops, index);
- BLI_assert(tottri <= f->len - 2);
+ BM_face_calc_tessellation(f, loops, index);
for (j = 0; j < tottri; j++) {
const float *p1 = loops[index[j][0]]->v->co;
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 92bd71e128a..e429e433a4b 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1811,7 +1811,7 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
BMFace *efa;
BMEdge *eed;
bool ok;
- bool change = false;
+ bool changed = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
@@ -1828,11 +1828,11 @@ bool EDBM_select_interior_faces(BMEditMesh *em)
if (ok) {
BM_face_select_set(bm, efa, true);
- change = true;
+ changed = true;
}
}
- return change;
+ return changed;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 203907226e3..fd391a31074 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -509,6 +509,18 @@ static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm)
(BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
(BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+#if 1 /* better support mixed cases [#37203] */
+ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+#endif
+
((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
(edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
(BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
@@ -3210,6 +3222,10 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
EDBM_op_init(em, &bmop, op, "triangulate faces=%hf quad_method=%i ngon_method=%i", BM_ELEM_SELECT, quad_method, ngon_method);
BMO_op_exec(em->bm, &bmop);
+ /* select the output */
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ EDBM_selectmode_flush(em);
+
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index deae9f17992..3daffe9bb37 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -200,7 +200,7 @@ static EnumPropertyItem prop_similar_types[] = {
static bool mball_select_similar_type(MetaBall *mb)
{
MetaElem *ml;
- bool change = false;
+ bool changed = false;
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) {
@@ -210,20 +210,20 @@ static bool mball_select_similar_type(MetaBall *mb)
if ((ml_iter->flag & SELECT) == 0) {
if (ml->type == ml_iter->type) {
ml_iter->flag |= SELECT;
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
static bool mball_select_similar_radius(MetaBall *mb, const float thresh)
{
MetaElem *ml;
- bool change = false;
+ bool changed = false;
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) {
@@ -233,20 +233,20 @@ static bool mball_select_similar_radius(MetaBall *mb, const float thresh)
if ((ml_iter->flag & SELECT) == 0) {
if (fabsf(ml_iter->rad - ml->rad) <= (thresh * ml->rad)) {
ml_iter->flag |= SELECT;
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
static bool mball_select_similar_stiffness(MetaBall *mb, const float thresh)
{
MetaElem *ml;
- bool change = false;
+ bool changed = false;
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) {
@@ -256,21 +256,21 @@ static bool mball_select_similar_stiffness(MetaBall *mb, const float thresh)
if ((ml_iter->flag & SELECT) == 0) {
if (fabsf(ml_iter->s - ml->s) <= thresh) {
ml_iter->flag |= SELECT;
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
static bool mball_select_similar_rotation(MetaBall *mb, const float thresh)
{
const float thresh_rad = thresh * (float)M_PI_2;
MetaElem *ml;
- bool change = false;
+ bool changed = false;
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) {
@@ -299,14 +299,14 @@ static bool mball_select_similar_rotation(MetaBall *mb, const float thresh)
angle_normalized_v3v3(ml_mat[2], ml_iter_mat[2])) < thresh_rad)
{
ml_iter->flag |= SELECT;
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
static int mball_select_similar_exec(bContext *C, wmOperator *op)
@@ -316,27 +316,27 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
float thresh = RNA_float_get(op->ptr, "threshold");
- bool change = false;
+ bool changed = false;
switch (type) {
case SIMMBALL_TYPE:
- change = mball_select_similar_type(mb);
+ changed = mball_select_similar_type(mb);
break;
case SIMMBALL_RADIUS:
- change = mball_select_similar_radius(mb, thresh);
+ changed = mball_select_similar_radius(mb, thresh);
break;
case SIMMBALL_STIFFNESS:
- change = mball_select_similar_stiffness(mb, thresh);
+ changed = mball_select_similar_stiffness(mb, thresh);
break;
case SIMMBALL_ROTATION:
- change = mball_select_similar_rotation(mb, thresh);
+ changed = mball_select_similar_rotation(mb, thresh);
break;
default:
BLI_assert(0);
break;
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 9dd686326bb..7e55d082883 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -999,7 +999,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
BKE_nlatrack_add_strip(nlt, strip);
/* auto-name the strip, and give the track an interesting name */
- strcpy(nlt->name, DATA_("SoundTrack"));
+ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
BKE_nlastrip_validate_name(adt, strip);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -1057,6 +1057,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win;
const short use_global = RNA_boolean_get(op->ptr, "use_global");
+ int num_deleted = 0;
if (CTX_data_edit_object(C))
return OPERATOR_CANCELLED;
@@ -1068,6 +1069,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
/* remove from current scene only */
ED_base_object_free_and_unlink(bmain, scene, base);
+ num_deleted++;
if (use_global) {
Scene *scene_iter;
@@ -1102,6 +1104,9 @@ static int object_delete_exec(bContext *C, wmOperator *op)
}
}
+ if (num_deleted > 0)
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %d objects", num_deleted);
+
return OPERATOR_FINISHED;
}
@@ -1113,7 +1118,6 @@ void OBJECT_OT_delete(wmOperatorType *ot)
ot->idname = "OBJECT_OT_delete";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = object_delete_exec;
ot->poll = ED_operator_objectmode;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 2e011493fce..465eb07f993 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -137,7 +137,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
View3D *v3d = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
Base *base;
- int changed = 0;
+ bool changed = false;
/* XXX need a context loop to handle such cases */
for (base = FIRSTBASE; base; base = base->next) {
@@ -145,7 +145,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
base->flag |= SELECT;
base->object->flag = base->flag;
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
}
}
if (changed) {
@@ -177,7 +177,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- short changed = 0;
+ bool changed = false;
const int unselected = RNA_boolean_get(op->ptr, "unselected");
CTX_DATA_BEGIN(C, Base *, base, visible_bases)
@@ -187,7 +187,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
base->flag &= ~SELECT;
base->object->flag = base->flag;
base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
if (base == BASACT) {
ED_base_object_activate(C, NULL);
}
@@ -196,7 +196,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
else {
if (!(base->flag & SELECT)) {
base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = 1;
+ changed = true;
if (base == BASACT) {
ED_base_object_activate(C, NULL);
}
@@ -237,14 +237,14 @@ void OBJECT_OT_hide_view_set(wmOperatorType *ot)
/* 99% same as above except no need for scene refreshing (TODO, update render preview) */
static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- short changed = 0;
+ bool changed = false;
/* XXX need a context loop to handle such cases */
CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
{
if (ob->restrictflag & OB_RESTRICT_RENDER) {
ob->restrictflag &= ~OB_RESTRICT_RENDER;
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index ce509e2ffe7..536f3f05ab2 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -142,6 +142,7 @@ void LATTICE_OT_select_more(struct wmOperatorType *ot);
void LATTICE_OT_select_less(struct wmOperatorType *ot);
void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot);
void LATTICE_OT_select_random(struct wmOperatorType *ot);
+void LATTICE_OT_select_mirror(struct wmOperatorType *ot);
void LATTICE_OT_make_regular(struct wmOperatorType *ot);
void LATTICE_OT_flip(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 3425aa08955..fdc9a604c07 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -49,6 +49,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -226,6 +227,78 @@ void LATTICE_OT_select_random(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
+
+/* -------------------------------------------------------------------- */
+/* Select Mirror Operator */
+
+static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const int axis = RNA_enum_get(op->ptr, "axis");
+ bool flip_uvw[3] = {false};
+ int tot, i;
+ BPoint *bp;
+ BLI_bitmap *selpoints;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ flip_uvw[axis] = true;
+
+ if (!extend) {
+ lt->actbp = LT_ACTBP_NONE;
+ }
+
+ /* store "original" selection */
+ selpoints = BLI_BITMAP_NEW(tot, __func__);
+ BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
+
+ /* actual (de)selection */
+ for (i = 0; i < tot; i++) {
+ const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
+ bp = &lt->def[i];
+ if (!bp->hide) {
+ if (BLI_BITMAP_GET(selpoints, i_flip)) {
+ bp->f1 |= SELECT;
+ }
+ else {
+ if (!extend) {
+ bp->f1 &= ~SELECT;
+ }
+ }
+ }
+ }
+
+
+ MEM_freeN(selpoints);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void LATTICE_OT_select_mirror(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select mirrored lattice points";
+ ot->idname = "LATTICE_OT_select_mirror";
+
+ /* api callbacks */
+ ot->exec = lattice_select_mirror_exec;
+ ot->poll = ED_operator_editlattice;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "axis", object_axis_unsigned_items, 0, "Axis", "");
+
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+}
+
+
/************************** Select More/Less Operator *************************/
static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
@@ -251,18 +324,13 @@ static int lattice_select_more_less(bContext *C, const bool select)
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
BPoint *bp;
const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
- int i, w, u, v;
+ int u, v, w;
BLI_bitmap *selpoints;
lt->actbp = LT_ACTBP_NONE;
- bp = lt->def;
selpoints = BLI_BITMAP_NEW(tot, __func__);
- for (i = 0; i < tot; i++, bp++) {
- if (bp->f1 & SELECT) {
- BLI_BITMAP_SET(selpoints, i);
- }
- }
+ BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
bp = lt->def;
for (w = 0; w < lt->pntsw; w++) {
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 80543d330b3..d4c64552b38 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -2220,7 +2220,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform);
-
+
if (!lmd)
return OPERATOR_CANCELLED;
if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 74ac487b687..efebbe8ddd7 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -224,6 +224,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(LATTICE_OT_select_less);
WM_operatortype_append(LATTICE_OT_select_ungrouped);
WM_operatortype_append(LATTICE_OT_select_random);
+ WM_operatortype_append(LATTICE_OT_select_mirror);
WM_operatortype_append(LATTICE_OT_make_regular);
WM_operatortype_append(LATTICE_OT_flip);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index c70a70c47b2..b3a2a7b6e0b 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1192,8 +1192,9 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER)
+ if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
+ }
}
}
CTX_DATA_END;
@@ -1212,7 +1213,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER) {
+ if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->reserved1 = TRACK_nZ;
data->reserved2 = UP_Y;
}
@@ -1234,7 +1235,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER) {
+ if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
data->lockflag = LOCK_Y;
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index ffa9eed65b9..fc83919144f 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -216,7 +216,7 @@ static EnumPropertyItem prop_select_linked_types[] = {
#if 0
static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -224,7 +224,7 @@ static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
base->flag |= SELECT;
base->object->flag = base->flag;
- changed = TRUE;
+ changed = true;
}
}
CTX_DATA_END;
@@ -233,9 +233,9 @@ static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
}
#endif
-static int object_select_all_by_obdata(bContext *C, void *obdata)
+static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -244,7 +244,7 @@ static int object_select_all_by_obdata(bContext *C, void *obdata)
base->flag |= SELECT;
base->object->flag = base->flag;
- changed = TRUE;
+ changed = true;
}
}
}
@@ -253,9 +253,9 @@ static int object_select_all_by_obdata(bContext *C, void *obdata)
return changed;
}
-static int object_select_all_by_material_texture(bContext *C, int use_texture, Material *mat, Tex *tex)
+static bool object_select_all_by_material_texture(bContext *C, int use_texture, Material *mat, Tex *tex)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -270,7 +270,7 @@ static int object_select_all_by_material_texture(bContext *C, int use_texture, M
if (!use_texture) {
if (mat1 == mat) {
base->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
else if (mat1 && use_texture) {
@@ -278,7 +278,7 @@ static int object_select_all_by_material_texture(bContext *C, int use_texture, M
if (mat1->mtex[b]) {
if (tex == mat1->mtex[b]->tex) {
base->flag |= SELECT;
- changed = TRUE;
+ changed = true;
break;
}
}
@@ -294,9 +294,9 @@ static int object_select_all_by_material_texture(bContext *C, int use_texture, M
return changed;
}
-static int object_select_all_by_dup_group(bContext *C, Object *ob)
+static bool object_select_all_by_dup_group(bContext *C, Object *ob)
{
- int changed = FALSE;
+ bool changed = false;
Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
@@ -307,7 +307,7 @@ static int object_select_all_by_dup_group(bContext *C, Object *ob)
base->flag |= SELECT;
base->object->flag = base->flag;
- changed = TRUE;
+ changed = true;
}
}
}
@@ -316,9 +316,9 @@ static int object_select_all_by_dup_group(bContext *C, Object *ob)
return changed;
}
-static int object_select_all_by_particle(bContext *C, Object *ob)
+static bool object_select_all_by_particle(bContext *C, Object *ob)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -331,7 +331,7 @@ static int object_select_all_by_particle(bContext *C, Object *ob)
for (psys_act = ob->particlesystem.first; psys_act; psys_act = psys_act->next) {
if (psys->part == psys_act->part) {
base->flag |= SELECT;
- changed = TRUE;
+ changed = true;
break;
}
}
@@ -349,9 +349,9 @@ static int object_select_all_by_particle(bContext *C, Object *ob)
return changed;
}
-static int object_select_all_by_library(bContext *C, Library *lib)
+static bool object_select_all_by_library(bContext *C, Library *lib)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -360,7 +360,7 @@ static int object_select_all_by_library(bContext *C, Library *lib)
base->flag |= SELECT;
base->object->flag = base->flag;
- changed = TRUE;
+ changed = true;
}
}
}
@@ -369,9 +369,9 @@ static int object_select_all_by_library(bContext *C, Library *lib)
return changed;
}
-static int object_select_all_by_library_obdata(bContext *C, Library *lib)
+static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
{
- int changed = FALSE;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
@@ -380,7 +380,7 @@ static int object_select_all_by_library_obdata(bContext *C, Library *lib)
base->flag |= SELECT;
base->object->flag = base->flag;
- changed = TRUE;
+ changed = true;
}
}
}
@@ -392,7 +392,7 @@ static int object_select_all_by_library_obdata(bContext *C, Library *lib)
void ED_object_select_linked_by_id(bContext *C, ID *id)
{
int idtype = GS(id->name);
- int changed = FALSE;
+ bool changed = false;
if (OB_DATA_SUPPORT_ID(idtype)) {
changed = object_select_all_by_obdata(C, id);
@@ -414,7 +414,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob;
int nr = RNA_enum_get(op->ptr, "type");
- short changed = FALSE, extend;
+ bool changed = false, extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -533,16 +533,16 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{0, NULL, 0, NULL, NULL}
};
-static short select_grouped_children(bContext *C, Object *ob, int recursive)
+static bool select_grouped_children(bContext *C, Object *ob, const bool recursive)
{
- short changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (ob == base->object->parent) {
if (!(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
if (recursive)
@@ -553,12 +553,12 @@ static short select_grouped_children(bContext *C, Object *ob, int recursive)
return changed;
}
-static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
+static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- short changed = 0;
+ bool changed = false;
Base *baspar, *basact = CTX_data_active_base(C);
if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
@@ -570,16 +570,16 @@ static short select_grouped_parent(bContext *C) /* Makes parent active and de-se
ED_base_object_select(basact, BA_DESELECT);
ED_base_object_select(baspar, BA_SELECT);
ED_base_object_activate(C, baspar);
- changed = 1;
+ changed = true;
}
return changed;
}
#define GROUP_MENU_MAX 24
-static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
+static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
{
- short changed = 0;
+ bool changed = false;
Group *group, *ob_groups[GROUP_MENU_MAX];
int group_count = 0, i;
uiPopupMenu *pup;
@@ -600,7 +600,7 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in
{
if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
@@ -620,12 +620,12 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in
return changed; /* The operator already handle this! */
}
-static short select_grouped_object_hooks(bContext *C, Object *ob)
+static bool select_grouped_object_hooks(bContext *C, Object *ob)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- short changed = 0;
+ bool changed = false;
Base *base;
ModifierData *md;
HookModifierData *hmd;
@@ -637,7 +637,7 @@ static short select_grouped_object_hooks(bContext *C, Object *ob)
base = BKE_scene_base_find(scene, hmd->object);
if (base && (BASE_SELECTABLE(v3d, base))) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
}
@@ -647,25 +647,25 @@ static short select_grouped_object_hooks(bContext *C, Object *ob)
/* Select objects with the same parent as the active (siblings),
* parent can be NULL also */
-static short select_grouped_siblings(bContext *C, Object *ob)
+static bool select_grouped_siblings(bContext *C, Object *ob)
{
- short changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_similar_lamps(bContext *C, Object *ob)
+static bool select_similar_lamps(bContext *C, Object *ob)
{
Lamp *la = ob->data;
- short changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
@@ -673,88 +673,88 @@ static short select_similar_lamps(bContext *C, Object *ob)
Lamp *la_test = base->object->data;
if ((la->type == la_test->type) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
}
CTX_DATA_END;
return changed;
}
-static short select_similar_pass_index(bContext *C, Object *ob)
+static bool select_similar_pass_index(bContext *C, Object *ob)
{
- char changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_grouped_type(bContext *C, Object *ob)
+static bool select_grouped_type(bContext *C, Object *ob)
{
- short changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_grouped_layer(bContext *C, Object *ob)
+static bool select_grouped_layer(bContext *C, Object *ob)
{
- char changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_grouped_index_object(bContext *C, Object *ob)
+static bool select_grouped_index_object(bContext *C, Object *ob)
{
- char changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_grouped_color(bContext *C, Object *ob)
+static bool select_grouped_color(bContext *C, Object *ob)
{
- char changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short objects_share_gameprop(Object *a, Object *b)
+static bool objects_share_gameprop(Object *a, Object *b)
{
bProperty *prop;
/*make a copy of all its properties*/
@@ -766,25 +766,25 @@ static short objects_share_gameprop(Object *a, Object *b)
return 0;
}
-static short select_grouped_gameprops(bContext *C, Object *ob)
+static bool select_grouped_gameprops(bContext *C, Object *ob)
{
- char changed = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
}
}
CTX_DATA_END;
return changed;
}
-static short select_grouped_keyingset(bContext *C, Object *UNUSED(ob))
+static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob))
{
KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
- short changed = 0;
+ bool changed = false;
/* firstly, validate KeyingSet */
if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
@@ -806,7 +806,7 @@ static short select_grouped_keyingset(bContext *C, Object *UNUSED(ob))
/* if id matches, select then stop looping (match found) */
if (ksp->id == (ID *)base->object) {
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ changed = true;
break;
}
}
@@ -822,7 +822,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob;
int nr = RNA_enum_get(op->ptr, "type");
- short changed = 0, extend;
+ bool changed = false, extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -830,7 +830,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
- changed = 1;
+ changed = true;
}
CTX_DATA_END;
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 6be4a2fed2c..5d10d67f0c9 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -341,16 +341,16 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- bool change = false;
+ bool changed = false;
if (RNA_boolean_get(op->ptr, "all")) {
- change = ED_object_shape_key_remove_all(bmain, ob);
+ changed = ED_object_shape_key_remove_all(bmain, ob);
}
else {
- change = ED_object_shape_key_remove(bmain, ob);
+ changed = ED_object_shape_key_remove(bmain, ob);
}
- if (change) {
+ if (changed) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index fef5ae392ea..63388600398 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -380,7 +380,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
- bool change = true;
+ bool changed = true;
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -391,14 +391,14 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
BKE_reportf(reports, RPT_ERROR,
"Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- change = false;
+ changed = false;
}
if (obdata->lib) {
BKE_reportf(reports, RPT_ERROR,
"Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- change = false;
+ changed = false;
}
}
@@ -412,22 +412,22 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
BKE_reportf(reports, RPT_ERROR,
"Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- change = false;
+ changed = false;
}
if (cu->key) {
BKE_reportf(reports, RPT_ERROR,
"Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- change = false;
+ changed = false;
}
}
}
CTX_DATA_END;
- if (!change)
+ if (!changed)
return OPERATOR_CANCELLED;
- change = false;
+ changed = false;
/* now execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -592,11 +592,11 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
- change = true;
+ changed = true;
}
CTX_DATA_END;
- if (!change) {
+ if (!changed) {
BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
return OPERATOR_CANCELLED;
}
@@ -608,7 +608,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- int change = 0;
+ bool changed = false;
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
@@ -619,11 +619,11 @@ static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
/* update for any children that may get moved */
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
- change = 1;
+ changed = true;
}
CTX_DATA_END;
- if (!change)
+ if (!changed)
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 16ee400fa67..f6761aab42c 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -2811,7 +2811,7 @@ static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformG
{
MDeformVert *dv;
const int def_nr = BLI_findindex(&ob->defbase, dg);
- bool change = false;
+ bool changed = false;
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
@@ -2830,7 +2830,7 @@ static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformG
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 */
- change = true;
+ changed = true;
}
}
}
@@ -2848,7 +2848,7 @@ static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformG
if (dv->dw && (allverts || (mv->flag & SELECT))) {
MDeformWeight *dw = defvert_find_index(dv, def_nr);
defvert_remove_group(dv, dw); /* dw can be NULL */
- change = true;
+ changed = true;
}
}
}
@@ -2870,13 +2870,13 @@ static bool vgroup_active_remove_verts(Object *ob, const bool allverts, bDeformG
dw = defvert_find_index(dv, def_nr);
defvert_remove_group(dv, dw); /* dw can be NULL */
- change = true;
+ changed = true;
}
}
}
}
- return change;
+ return changed;
}
static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
@@ -3077,16 +3077,16 @@ static void vgroup_assign_verts(Object *ob, const float weight)
/* removes from all defgroup, if allverts==0 only selected vertices */
static bool vgroup_remove_verts(Object *ob, int allverts)
{
- bool change = false;
+ 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) {
- change |= vgroup_active_remove_verts(ob, allverts, dg);
+ changed |= vgroup_active_remove_verts(ob, allverts, dg);
}
- return change;
+ return changed;
}
/********************** vertex group operators *********************/
@@ -3965,22 +3965,22 @@ void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
{
Object *obact = ED_object_context(C);
- int change = 0;
+ int changed_tot = 0;
int fail = 0;
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (obact != ob) {
- if (ED_vgroup_array_copy(ob, obact)) change++;
+ if (ED_vgroup_array_copy(ob, obact)) changed_tot++;
else fail++;
}
}
CTX_DATA_END;
- if ((change == 0 && fail == 0) || fail) {
+ if ((changed_tot == 0 && fail == 0) || fail) {
BKE_reportf(op->reports, RPT_ERROR,
"Copy vertex groups to selected: %d done, %d failed (object data must have matching indices)",
- change, fail);
+ changed_tot, fail);
}
return OPERATOR_FINISHED;
@@ -4010,7 +4010,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
char dg_act_name[MAX_VGROUP_NAME]; /* may be freed so copy */
int fail = 0;
- bool change = false;
+ 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");
@@ -4060,7 +4060,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
}
if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) {
- change = true;
+ changed = true;
}
else {
fail++;
@@ -4072,7 +4072,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
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)) {
- change = true;
+ changed = true;
}
else {
fail++;
@@ -4088,7 +4088,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- if (change) {
+ if (changed) {
/* possible the active vertex group changed because of adding/removing */
/* note!, dg_act may be realloc'd, only check its not NULL */
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 65a3e5b558e..808c7cc3e82 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -2978,7 +2978,7 @@ static void brush_puff(PEData *data, int point_index)
float co_prev[3], co[3]; /* track key coords as we loop (global-space) */
float fac = 0.0f, length_accum = 0.0f;
bool puff_volume = false;
- bool change = false;
+ bool changed = false;
zero_v3(ofs_prev);
@@ -3056,7 +3056,7 @@ static void brush_puff(PEData *data, int point_index)
* keys that come after */
sub_v3_v3v3(ofs_prev, key->co, dco);
}
- change = true;
+ changed = true;
}
else {
@@ -3116,7 +3116,7 @@ static void brush_puff(PEData *data, int point_index)
}
}
- if (change)
+ if (changed)
point->flag |= PEP_EDIT_RECALC;
}
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 698d530c22d..00b9940121c 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -123,7 +123,7 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
Object *ob = (scene) ? OBACT : NULL;
int type = RNA_enum_get(op->ptr, "type");
- bool change;
+ bool changed;
/* sanity checks */
if (ELEM(NULL, scene, rbw)) {
@@ -131,9 +131,9 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* apply to active object */
- change = ED_rigidbody_constraint_add(scene, ob, type, op->reports);
+ changed = ED_rigidbody_constraint_add(scene, ob, type, op->reports);
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 00304090818..ae6af7c2e0b 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -145,12 +145,12 @@ static int rigidbody_object_add_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
int type = RNA_enum_get(op->ptr, "type");
- bool change;
+ bool changed;
/* apply to active object */
- change = ED_rigidbody_object_add(scene, ob, type, op->reports);
+ changed = ED_rigidbody_object_add(scene, ob, type, op->reports);
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
@@ -187,15 +187,15 @@ static int rigidbody_object_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
- bool change = false;
+ bool changed = false;
/* apply to active object */
if (!ELEM(NULL, ob, ob->rigidbody_object)) {
ED_rigidbody_object_remove(scene, ob);
- change = true;
+ changed = true;
}
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
@@ -233,15 +233,15 @@ static int rigidbody_objects_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
int type = RNA_enum_get(op->ptr, "type");
- bool change = false;
+ bool changed = false;
/* create rigid body objects and add them to the world's group */
CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
- change |= ED_rigidbody_object_add(scene, ob, type, op->reports);
+ changed |= ED_rigidbody_object_add(scene, ob, type, op->reports);
}
CTX_DATA_END;
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
@@ -277,19 +277,19 @@ void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- bool change = false;
+ bool changed = false;
/* apply this to all selected objects... */
CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
{
if (ob->rigidbody_object) {
ED_rigidbody_object_remove(scene, ob);
- change = true;
+ changed = true;
}
}
CTX_DATA_END;
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
@@ -325,7 +325,7 @@ void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
{
int shape = RNA_enum_get(op->ptr, "type");
- bool change = false;
+ bool changed = false;
/* apply this to all selected objects... */
CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
@@ -339,12 +339,12 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
- change = true;
+ changed = true;
}
}
CTX_DATA_END;
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
@@ -555,7 +555,7 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
{
int material = RNA_enum_get(op->ptr, "material");
float density;
- bool change = false;
+ bool changed = false;
/* get density (kg/m^3) to apply */
if (material >= 0) {
@@ -592,12 +592,12 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
- change = true;
+ changed = true;
}
}
CTX_DATA_END;
- if (change) {
+ if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 71bf67220fe..e1a271e996b 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -677,7 +677,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->v3d_override = true;
if (v3d->localvd)
- rj->lay_override = scene->lay | v3d->localvd->lay;
+ rj->lay_override |= v3d->localvd->lay;
}
/* setup job */
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 2bf8a48edc4..081187ef1d8 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -358,13 +358,14 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
/* turn off bounce lights for volume,
* doesn't make much visual difference and slows it down too */
- if (mat->material_type == MA_TYPE_VOLUME) {
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->type == OB_LAMP) {
- /* if doesn't match 'Lamp.002' --> main key light */
- if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
+ for (base = sce->base.first; base; base = base->next) {
+ if (base->object->type == OB_LAMP) {
+ /* if doesn't match 'Lamp.002' --> main key light */
+ if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
+ if (mat->material_type == MA_TYPE_VOLUME)
base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
+ else
+ base->object->restrictflag &= ~OB_RESTRICT_RENDER;
}
}
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index fccce0357a4..701abab804f 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -39,6 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_linklist_stack.h"
#include "BLF_translation.h"
@@ -160,8 +162,8 @@ static void area_draw_azone(short x1, short y1, short x2, short y2)
int dx = x2 - x1;
int dy = y2 - y1;
- dx = copysign(ceilf(0.3f * fabsf(dx)), dx);
- dy = copysign(ceilf(0.3f * fabsf(dy)), dy);
+ dx = copysign(ceilf(0.3f * abs(dx)), dx);
+ dy = copysign(ceilf(0.3f * abs(dy)), dy);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -859,10 +861,10 @@ static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
static int rct_fits(rcti *rect, char dir, int size)
{
if (dir == 'h') {
- return BLI_rcti_size_x(rect) - size;
+ return BLI_rcti_size_x(rect) + 1 - size;
}
else { /* 'v' */
- return BLI_rcti_size_y(rect) - size;
+ return BLI_rcti_size_y(rect) + 1 - size;
}
}
@@ -1157,16 +1159,16 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
{
- short rt = U.pixelsize > 1.0f ? 1 : 0;
+ short rt = (short) U.pixelsize;
- if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + 1 + rt;
+ if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + rt;
else sa->totrct.xmin = sa->v1->vec.x;
- if (sa->v4->vec.x < sizex - 1) sa->totrct.xmax = sa->v4->vec.x - 1 - rt;
+ if (sa->v4->vec.x < sizex - 1) sa->totrct.xmax = sa->v4->vec.x - rt;
else sa->totrct.xmax = sa->v4->vec.x;
- if (sa->v1->vec.y > 0) sa->totrct.ymin = sa->v1->vec.y + 1 + rt;
+ if (sa->v1->vec.y > 0) sa->totrct.ymin = sa->v1->vec.y + rt;
else sa->totrct.ymin = sa->v1->vec.y;
- if (sa->v2->vec.y < sizey - 1) sa->totrct.ymax = sa->v2->vec.y - 1 - rt;
+ if (sa->v2->vec.y < sizey - 1) sa->totrct.ymax = sa->v2->vec.y - rt;
else sa->totrct.ymax = sa->v2->vec.y;
/* for speedup */
@@ -1566,12 +1568,15 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
Panel *panel;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
- int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
+ int x, y, xco, yco, w, em, triangle, open;
+ bool is_context_new = 0;
int redo;
int scroll;
+ BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
+
if (contextnr >= 0)
- newcontext = UI_view2d_tab_set(v2d, contextnr);
+ is_context_new = UI_view2d_tab_set(v2d, contextnr);
/* before setting the view */
if (vertical) {
@@ -1591,7 +1596,22 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
}
scroll = v2d->scroll;
-
+
+
+ /* collect panels to draw */
+ for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
+ /* verify context */
+ if (context && pt->context[0] && !STREQ(context, pt->context)) {
+ continue;
+ }
+
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ BLI_SMALLSTACK_PUSH(pt_stack, pt);
+ }
+ }
+
+
/* sortof hack - but we cannot predict the height of panels, until it's being generated */
/* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
/* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
@@ -1612,63 +1632,57 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
/* set view2d view matrix - uiBeginBlock() stores it */
UI_view2d_view_ortho(v2d);
- for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
- /* verify context */
- if (context)
- if (pt->context[0] && strcmp(context, pt->context) != 0)
- continue;
+ BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
+ {
+ block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+ panel = uiBeginPanel(sa, ar, block, pt, &open);
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
- panel = uiBeginPanel(sa, ar, block, pt, &open);
+ /* bad fixed values */
+ triangle = (int)(UI_UNIT_Y * 1.1f);
- /* bad fixed values */
- triangle = (int)(UI_UNIT_Y * 1.1f);
+ if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for enabled buttons */
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
- if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- /* for enabled buttons */
- panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
+ pt->draw_header(C, panel);
- pt->draw_header(C, panel);
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->labelofs = xco - triangle;
+ panel->layout = NULL;
+ }
+ else {
+ panel->labelofs = 0;
+ }
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->labelofs = xco - triangle;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
+ if (open) {
+ short panelContext;
- if (open) {
- short panelContext;
-
- /* panel context can either be toolbar region or normal panels region */
- if (ar->regiontype == RGN_TYPE_TOOLS)
- panelContext = UI_LAYOUT_TOOLBAR;
- else
- panelContext = UI_LAYOUT_PANEL;
-
- panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
- style->panelspace, 0, w - 2 * style->panelspace, em, style);
-
- pt->draw(C, panel);
-
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->layout = NULL;
-
- yco -= 2 * style->panelspace;
- uiEndPanel(block, w, -yco);
- }
- else {
- yco = 0;
- uiEndPanel(block, w, 0);
- }
+ /* panel context can either be toolbar region or normal panels region */
+ if (ar->regiontype == RGN_TYPE_TOOLS)
+ panelContext = UI_LAYOUT_TOOLBAR;
+ else
+ panelContext = UI_LAYOUT_PANEL;
- uiEndBlock(C, block);
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 0, w - 2 * style->panelspace, em, style);
+
+ pt->draw(C, panel);
+
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->layout = NULL;
+
+ yco -= 2 * style->panelspace;
+ uiEndPanel(block, w, -yco);
}
+ else {
+ yco = 0;
+ uiEndPanel(block, w, 0);
+ }
+
+ uiEndBlock(C, block);
}
+ BLI_SMALLSTACK_ITER_END;
/* align panels and return size */
uiEndPanels(C, ar, &x, &y);
@@ -1683,7 +1697,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
}
else {
/* don't jump back when panels close or hide */
- if (!newcontext)
+ if (!is_context_new)
x = max_ii(x, v2d->cur.xmax);
y = -y;
}
@@ -1705,6 +1719,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
}
}
+ BLI_SMALLSTACK_FREE(pt_stack);
/* clear */
if (ar->overlap) {
@@ -1824,7 +1839,7 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co
/* box fill entire width or just around text */
if (!block)
- rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text) + 1.2f * U.widget_unit);
+ rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit);
rect.ymax = BLI_rcti_size_y(&ar->winrct);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index d356c3d8de3..57d97178be5 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -143,7 +143,7 @@ void fdrawbezier(float vec[4][3])
float dist;
float curve_res = 24, spline_step = 0.0f;
- dist = 0.5f * ABS(vec[0][0] - vec[3][0]);
+ dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
/* check direction later, for top sockets */
vec[1][0] = vec[0][0] + dist;
@@ -981,7 +981,9 @@ void bgl_get_mats(bglMats *mats)
/* *************** glPolygonOffset hack ************* */
-/* dist is only for ortho now... */
+/**
+ * \note \a viewdist is only for ortho at the moment.
+ */
void bglPolygonOffset(float viewdist, float dist)
{
static float winmat[16], offset = 0.0;
@@ -1157,3 +1159,10 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings);
}
+
+void cpack(unsigned int x)
+{
+ glColor3ub( ( (x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF) );
+}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 356db174c2f..61d28a45fac 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -264,7 +264,10 @@ int scredge_is_horizontal(ScrEdge *se)
return (se->v1->vec.y == se->v2->vec.y);
}
-ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
+/* need win size to make sure not to include edges along screen edge */
+ScrEdge *screen_find_active_scredge(bScreen *sc,
+ const int winsize_x, const int winsize_y,
+ const int mx, const int my)
{
ScrEdge *se;
int safety = U.widget_unit / 10;
@@ -273,20 +276,24 @@ ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
for (se = sc->edgebase.first; se; se = se->next) {
if (scredge_is_horizontal(se)) {
- short min, max;
- min = MIN2(se->v1->vec.x, se->v2->vec.x);
- max = MAX2(se->v1->vec.x, se->v2->vec.x);
-
- if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
- return se;
+ if (se->v1->vec.y > 0 && se->v1->vec.y < winsize_y - 1) {
+ short min, max;
+ min = MIN2(se->v1->vec.x, se->v2->vec.x);
+ max = MAX2(se->v1->vec.x, se->v2->vec.x);
+
+ if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
+ return se;
+ }
}
else {
- short min, max;
- min = MIN2(se->v1->vec.y, se->v2->vec.y);
- max = MAX2(se->v1->vec.y, se->v2->vec.y);
-
- if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
- return se;
+ if (se->v1->vec.x > 0 && se->v1->vec.x < winsize_x - 1) {
+ short min, max;
+ min = MIN2(se->v1->vec.y, se->v2->vec.y);
+ max = MAX2(se->v1->vec.y, se->v2->vec.y);
+
+ if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
+ return se;
+ }
}
}
@@ -453,6 +460,9 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
/* uses window size */
bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
{
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
@@ -463,9 +473,9 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
sc->winid = win->winid;
sv1 = screen_addvert(sc, 0, 0);
- sv2 = screen_addvert(sc, 0, WM_window_pixels_y(win) - 1);
- sv3 = screen_addvert(sc, WM_window_pixels_x(win) - 1, WM_window_pixels_y(win) - 1);
- sv4 = screen_addvert(sc, WM_window_pixels_x(win) - 1, 0);
+ sv2 = screen_addvert(sc, 0, winsize_y - 1);
+ sv3 = screen_addvert(sc, winsize_x - 1, winsize_y - 1);
+ sv4 = screen_addvert(sc, winsize_x - 1, 0);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
@@ -655,11 +665,16 @@ void select_connected_scredge(bScreen *sc, ScrEdge *edge)
}
/* test if screen vertices should be scaled */
-static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
+static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
{
+ /* clamp Y size of header sized areas when expanding windows
+ * avoids annoying empty space around file menu */
+#define USE_HEADER_SIZE_CLAMP
+
+ const int headery_init = ED_area_headersize();
ScrVert *sv = NULL;
ScrArea *sa;
- int sizex, sizey;
+ int winsize_x_prev, winsize_y_prev;
float facx, facy, tempf, min[2], max[2];
/* calculate size */
@@ -677,14 +692,41 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
sv->vec.y -= min[1];
}
- sizex = max[0] - min[0];
- sizey = max[1] - min[1];
-
- if (sizex != winsizex || sizey != winsizey) {
- facx = winsizex;
- facx /= (float)sizex;
- facy = winsizey;
- facy /= (float)sizey;
+ winsize_x_prev = (max[0] - min[0]) + 1;
+ winsize_y_prev = (max[1] - min[1]) + 1;
+
+
+#ifdef USE_HEADER_SIZE_CLAMP
+#define TEMP_BOTTOM 1
+#define TEMP_TOP 2
+
+ /* if the window's Y axis grows, clamp header sized areas */
+ if (winsize_y_prev < winsize_y) { /* growing? */
+ const int headery_margin_max = headery_init + 4;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ sa->temp = 0;
+
+ if (ar && !(ar->flag & RGN_FLAG_HIDDEN)) {
+ if (sa->v2->vec.y == winsize_y_prev - 1) {
+ if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
+ sa->temp = TEMP_TOP;
+ }
+ }
+ else if (sa->v1->vec.y == 0) {
+ if ((sa->v2->vec.y - sa->v1->vec.y) < headery_margin_max) {
+ sa->temp = TEMP_BOTTOM;
+ }
+ }
+ }
+ }
+ }
+#endif
+
+
+ if (winsize_x_prev != winsize_x || winsize_y_prev != winsize_y) {
+ facx = ((float)winsize_x) / ((float)winsize_x_prev - 1);
+ facy = ((float)winsize_y) / ((float)winsize_y_prev - 1);
/* make sure it fits! */
for (sv = sc->vertbase.first; sv; sv = sv->next) {
@@ -695,25 +737,79 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
//sv->vec.x += AREAGRID - 1;
//sv->vec.x -= (sv->vec.x % AREAGRID);
- CLAMP(sv->vec.x, 0, winsizex);
+ CLAMP(sv->vec.x, 0, winsize_x - 1);
tempf = ((float)sv->vec.y) * facy;
sv->vec.y = (short)(tempf + 0.5f);
//sv->vec.y += AREAGRID - 1;
//sv->vec.y -= (sv->vec.y % AREAGRID);
- CLAMP(sv->vec.y, 0, winsizey);
+ CLAMP(sv->vec.y, 0, winsize_y - 1);
}
}
-
+
+
+#ifdef USE_HEADER_SIZE_CLAMP
+ if (winsize_y_prev < winsize_y) { /* growing? */
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ScrEdge *se = NULL;
+
+ if (sa->temp == 0)
+ continue;
+
+ if (sa->v1 == sa->v2)
+ continue;
+
+ /* adjust headery if verts are along the edge of window */
+ if (sa->temp == TEMP_TOP) {
+ /* lower edge */
+ const int yval = sa->v2->vec.y - headery_init;
+ se = screen_findedge(sc, sa->v4, sa->v1);
+ select_connected_scredge(sc, se);
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ if (sv != sa->v2 && sv != sa->v3) {
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
+ }
+ }
+ }
+ else {
+ /* upper edge */
+ const int yval = sa->v1->vec.y + headery_init;
+ se = screen_findedge(sc, sa->v2, sa->v3);
+ select_connected_scredge(sc, se);
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ if (sv != sa->v1 && sv != sa->v4) {
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
+ }
+ }
+ }
+ }
+ }
+
+#undef USE_HEADER_SIZE_CLAMP
+#undef TEMP_BOTTOM
+#undef TEMP_TOP
+#endif
+
+
/* test for collapsed areas. This could happen in some blender version... */
/* ton: removed option now, it needs Context... */
/* make each window at least ED_area_headersize() high */
for (sa = sc->areabase.first; sa; sa = sa->next) {
- int headery = ED_area_headersize() + U.pixelsize;
+ int headery = headery_init;
+
+ /* adjust headery if verts are along the edge of window */
+ if (sa->v1->vec.y > 0)
+ headery += U.pixelsize;
+ if (sa->v2->vec.y < winsize_y - 1)
+ headery += U.pixelsize;
- if (sa->v1->vec.y + headery > sa->v2->vec.y) {
+ if (sa->v2->vec.y - sa->v1->vec.y + 1 < headery) {
/* lower edge */
ScrEdge *se = screen_findedge(sc, sa->v4, sa->v1);
if (se && sa->v1 != sa->v2) {
@@ -722,14 +818,14 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
select_connected_scredge(sc, se);
/* all selected vertices get the right offset */
- yval = sa->v2->vec.y - headery;
- sv = sc->vertbase.first;
- while (sv) {
+ yval = sa->v2->vec.y - headery + 1;
+ for (sv = sc->vertbase.first; sv; sv = sv->next) {
/* if is a collapsed area */
if (sv != sa->v2 && sv != sa->v3) {
- if (sv->flag) sv->vec.y = yval;
+ if (sv->flag) {
+ sv->vec.y = yval;
+ }
}
- sv = sv->next;
}
}
}
@@ -947,7 +1043,7 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, int center)
if (U.pixelsize > 1.0f) {
glColor3ub(0x50, 0x50, 0x50);
- glLineWidth(1.5f * U.pixelsize);
+ glLineWidth((2.0f * U.pixelsize) - 1);
drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0);
glLineWidth(1.0f);
}
@@ -1022,6 +1118,9 @@ void ED_screen_do_listen(bContext *C, wmNotifier *note)
/* only for edge lines between areas, and the blended join arrows */
void ED_screen_draw(wmWindow *win)
{
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
ScrArea *sa;
ScrArea *sa1 = NULL;
ScrArea *sa2 = NULL;
@@ -1035,10 +1134,10 @@ void ED_screen_draw(wmWindow *win)
if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa;
- drawscredge_area(sa, WM_window_pixels_x(win), WM_window_pixels_y(win), 0);
+ drawscredge_area(sa, winsize_x, winsize_y, 0);
}
for (sa = win->screen->areabase.first; sa; sa = sa->next)
- drawscredge_area(sa, WM_window_pixels_x(win), WM_window_pixels_y(win), 1);
+ drawscredge_area(sa, winsize_x, winsize_y, 1);
/* blended join arrow */
if (sa1 && sa2) {
@@ -1107,18 +1206,20 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
{
/* exception for bg mode, we only need the screen context */
if (!G.background) {
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
ScrArea *sa;
rcti winrct;
winrct.xmin = 0;
- winrct.xmax = WM_window_pixels_x(win) - 1;
+ winrct.xmax = winsize_x - 1;
winrct.ymin = 0;
- winrct.ymax = WM_window_pixels_y(win) - 1;
+ winrct.ymax = winsize_y - 1;
/* header size depends on DPI, let's verify */
screen_refresh_headersizes();
- screen_test_scale(win->screen, WM_window_pixels_x(win), WM_window_pixels_y(win));
+ screen_test_scale(win->screen, winsize_x, winsize_y);
if (win->screen->mainwin == 0)
win->screen->mainwin = wm_subwindow_open(win, &winrct);
@@ -1133,7 +1234,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
/* wake up animtimer */
if (win->screen->animtimer)
- WM_event_timer_sleep(wm, win, win->screen->animtimer, 0);
+ WM_event_timer_sleep(wm, win, win->screen->animtimer, false);
}
if (G.debug & G_DEBUG_EVENTS) {
@@ -1245,6 +1346,9 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* case when on area-edge or in azones, or outside window */
static void screen_cursor_set(wmWindow *win, wmEvent *event)
{
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
AZone *az = NULL;
ScrArea *sa;
@@ -1263,7 +1367,7 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event)
}
}
else {
- ScrEdge *actedge = screen_find_active_scredge(win->screen, event->x, event->y);
+ ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y);
if (actedge) {
if (scredge_is_horizontal(actedge))
@@ -1410,7 +1514,7 @@ void ED_screen_set(bContext *C, bScreen *sc)
/* we put timer to sleep, so screen_exit has to think there's no timer */
oldscreen->animtimer = NULL;
if (wt)
- WM_event_timer_sleep(wm, win, wt, 1);
+ WM_event_timer_sleep(wm, win, wt, true);
ED_screen_exit(C, win, oldscreen);
oldscreen->animtimer = wt;
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index b811fc46188..66677aed68f 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -53,7 +53,9 @@ void removedouble_scrverts(bScreen *sc);
void removedouble_scredges(bScreen *sc);
void removenotused_scredges(bScreen *sc);
int scredge_is_horizontal(ScrEdge *se);
-ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my);
+ScrEdge *screen_find_active_scredge(bScreen *sc,
+ const int winsize_x, const int winsize_y,
+ const int mx, const int my);
struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 93923c24c84..b5d7030ef82 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -695,8 +695,12 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
sActionzoneData *sad = op->customdata;
-
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
switch (event->type) {
case MOUSEMOVE:
{
@@ -719,7 +723,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* once we drag outside the actionzone, register a gesture
* check we're not on an edge so join finds the other area */
is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) &&
- (screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y) == NULL));
+ (screen_find_active_scredge(sc, winsize_x, winsize_y, event->x, event->y) == NULL));
}
else {
const int delta_min = 1;
@@ -988,18 +992,30 @@ typedef struct sAreaMoveData {
char dir;
} sAreaMoveData;
-/* helper call to move area-edge, sets limits */
-static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
+/* helper call to move area-edge, sets limits
+ * need window size in order to get correct limits */
+static void area_move_set_limits(bScreen *sc, int dir,
+ const int winsize_x, const int winsize_y,
+ int *bigger, int *smaller)
{
ScrArea *sa;
- int areaminy = ED_area_headersize() + U.pixelsize; // pixelsize is used as area divider
+ int areaminy = ED_area_headersize();
+ int areamin;
/* we check all areas and test for free space with MINSIZE */
*bigger = *smaller = 100000;
for (sa = sc->areabase.first; sa; sa = sa->next) {
if (dir == 'h') {
- int y1 = sa->v2->vec.y - sa->v1->vec.y - areaminy;
+ int y1;
+ areamin = areaminy;
+
+ if (sa->v1->vec.y > 0)
+ areamin += U.pixelsize;
+ if (sa->v2->vec.y < winsize_y - 1)
+ areamin += U.pixelsize;
+
+ y1 = sa->v2->vec.y - sa->v1->vec.y + 1 - areamin;
/* if top or down edge selected, test height */
if (sa->v1->editflag && sa->v4->editflag)
@@ -1008,7 +1024,15 @@ static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller
*smaller = min_ii(*smaller, y1);
}
else {
- int x1 = sa->v4->vec.x - sa->v1->vec.x - AREAMINX;
+ int x1;
+ areamin = AREAMINX;
+
+ if (sa->v1->vec.x > 0)
+ areamin += U.pixelsize;
+ if (sa->v4->vec.x < winsize_x - 1)
+ areamin += U.pixelsize;
+
+ x1 = sa->v4->vec.x - sa->v1->vec.x + 1 - areamin;
/* if left or right edge selected, test width */
if (sa->v1->editflag && sa->v2->editflag)
@@ -1024,9 +1048,12 @@ static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller
static int area_move_init(bContext *C, wmOperator *op)
{
bScreen *sc = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
ScrEdge *actedge;
sAreaMoveData *md;
ScrVert *v1;
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
int x, y;
/* required properties */
@@ -1034,7 +1061,7 @@ static int area_move_init(bContext *C, wmOperator *op)
y = RNA_int_get(op->ptr, "y");
/* setup */
- actedge = screen_find_active_scredge(sc, x, y);
+ actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, x, y);
if (actedge == NULL) return 0;
md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
@@ -1049,7 +1076,7 @@ static int area_move_init(bContext *C, wmOperator *op)
for (v1 = sc->vertbase.first; v1; v1 = v1->next)
v1->editflag = v1->flag;
- area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
+ area_move_set_limits(sc, md->dir, winsize_x, winsize_y, &md->bigger, &md->smaller);
return 1;
}
@@ -1058,39 +1085,53 @@ static int area_move_init(bContext *C, wmOperator *op)
static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
{
wmWindow *win = CTX_wm_window(C);
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
bScreen *sc = CTX_wm_screen(C);
ScrVert *v1;
ScrArea *sa;
- int areaminy = ED_area_headersize() + 1;
+ int doredraw = 0;
+ int oldval;
delta = CLAMPIS(delta, -smaller, bigger);
for (v1 = sc->vertbase.first; v1; v1 = v1->next) {
if (v1->editflag) {
/* that way a nice AREAGRID */
- if ((dir == 'v') && v1->vec.x > 0 && v1->vec.x < WM_window_pixels_x(win) - 1) {
+ if ((dir == 'v') && v1->vec.x > 0 && v1->vec.x < winsize_x - 1) {
+ oldval = v1->vec.x;
v1->vec.x = origval + delta;
- if (delta != bigger && delta != -smaller) v1->vec.x -= (v1->vec.x % AREAGRID);
+
+ if (delta != bigger && delta != -smaller) {
+ v1->vec.x -= (v1->vec.x % AREAGRID);
+ v1->vec.x = CLAMPIS(v1->vec.x, origval - smaller, origval + bigger);
+ }
+ if (oldval != v1->vec.x)
+ doredraw = 1;
}
- if ((dir == 'h') && v1->vec.y > 0 && v1->vec.y < WM_window_pixels_y(win) - 1) {
+ if ((dir == 'h') && v1->vec.y > 0 && v1->vec.y < winsize_y - 1) {
+ oldval = v1->vec.y;
v1->vec.y = origval + delta;
- v1->vec.y += AREAGRID - 1;
- v1->vec.y -= (v1->vec.y % AREAGRID);
-
- /* prevent too small top header */
- if (v1->vec.y > WM_window_pixels_y(win) - areaminy)
- v1->vec.y = WM_window_pixels_y(win) - areaminy;
+ if (delta != bigger && delta != smaller) {
+ v1->vec.y -= (v1->vec.y % AREAGRID);
+ v1->vec.y = CLAMPIS(v1->vec.y, origval - smaller, origval + bigger);
+ }
+ if (oldval != v1->vec.y)
+ doredraw = 1;
}
}
}
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag)
- ED_area_tag_redraw(sa);
- }
+ /* only redraw if we actually moved a screen vert, for AREAGRID */
+ if (doredraw) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag)
+ ED_area_tag_redraw(sa);
+ }
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
+ }
}
static void area_move_apply(bContext *C, wmOperator *op)
@@ -1410,11 +1451,15 @@ static void area_split_exit(bContext *C, wmOperator *op)
/* UI callback, adds new handler */
static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
sAreaSplitData *sd;
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
int dir;
/* no full window splitting allowed */
- if (CTX_wm_screen(C)->full != SCREENNORMAL)
+ if (sc->full != SCREENNORMAL)
return OPERATOR_CANCELLED;
if (event->type == EVT_ACTIONZONE_AREA) {
@@ -1463,7 +1508,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else
y = event->x;
- actedge = screen_find_active_scredge(CTX_wm_screen(C), x, y);
+ actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, x, y);
if (actedge == NULL)
return OPERATOR_CANCELLED;
@@ -1486,7 +1531,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* do the split */
if (area_split_apply(C, op)) {
- area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller);
+ area_move_set_limits(sc, dir, winsize_x, winsize_y, &sd->bigger, &sd->smaller);
/* add temp handler for edge move or cancel */
WM_event_add_modal_handler(C, op);
@@ -2574,10 +2619,16 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
uiPopupMenu *pup;
uiLayout *layout;
PointerRNA ptr1, ptr2;
- ScrEdge *actedge = screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y);
+ ScrEdge *actedge;
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
+ actedge = screen_find_active_scredge(sc, winsize_x, winsize_y, event->x, event->y);
if (actedge == NULL) return OPERATOR_CANCELLED;
@@ -2878,7 +2929,6 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
ot->idname = "SCREEN_OT_region_quadview";
/* api callbacks */
- // ot->invoke = WM_operator_confirm;
ot->exec = region_quadview_exec;
ot->poll = ED_operator_region_view3d_active;
ot->flag = 0;
@@ -3556,9 +3606,6 @@ static void SCREEN_OT_new(wmOperatorType *ot)
/* api callbacks */
ot->exec = screen_new_exec;
ot->poll = WM_operator_winactive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* delete screen operator *********************/
@@ -3575,15 +3622,12 @@ static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
static void SCREEN_OT_delete(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete Screen"; /* was scene */
+ ot->name = "Delete Screen";
ot->description = "Delete active screen";
ot->idname = "SCREEN_OT_delete";
/* api callbacks */
ot->exec = screen_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* new scene operator *********************/
@@ -4032,12 +4076,6 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "next", FALSE);
- kmi = WM_keymap_add_item(keymap, "SCREEN_OT_marker_jump", RIGHTARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "next", TRUE);
-
- kmi = WM_keymap_add_item(keymap, "SCREEN_OT_marker_jump", LEFTARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "next", FALSE);
-
/* play (forward and backwards) */
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 56143d00afe..8f4454eb2da 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -569,7 +569,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
glTranslatef(-0.5f, -0.5f, 0);
/* scale based on tablet pressure */
- if (primary && ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
glTranslatef(0.5f, 0.5f, 0);
glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
glTranslatef(-0.5f, -0.5f, 0);
@@ -694,7 +694,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
/* scale based on tablet pressure */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
do_pop = true;
glPushMatrix();
glLoadIdentity();
@@ -788,7 +788,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
projected_radius);
/* scale 3D brush radius by pressure */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush))
+ if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush))
unprojected_radius *= ups->pressure_value;
/* set cached value in either Brush or UnifiedPaintSettings */
@@ -828,11 +828,10 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
outline_col = brush->add_col;
final_radius = BKE_brush_size_get(scene, brush) * zoomx;
- if (brush->flag & BRUSH_RAKE)
- /* here, translation contains the mouse coordinates. */
+ /* don't calculate rake angles while a stroke is active because the rake variables are global and
+ * we may get interference with the stroke itself. For line strokes, such interference is visible */
+ if (!ups->stroke_active && (brush->flag & BRUSH_RAKE))
paint_calculate_rake_rotation(ups, translation);
- else if (!(brush->flag & BRUSH_ANCHORED))
- ups->brush_rotation = 0.0;
/* draw overlay */
paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
@@ -883,7 +882,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
glTranslatef(translation[0], translation[1], 0);
/* draw an inner brush */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
+ if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
/* inner at full alpha */
glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->pressure_value, 40);
/* outer at half alpha */
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 345db7a0ed0..0eb019afbf7 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -100,7 +100,8 @@ static void partialvis_update_mesh(Object *ob,
MVert *mvert;
float *paint_mask;
int *vert_indices;
- int any_changed = 0, any_visible = 0, totvert, i;
+ int totvert, i;
+ bool any_changed = false, any_visible = false;
BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
@@ -118,11 +119,11 @@ static void partialvis_update_mesh(Object *ob,
v->flag |= ME_HIDE;
else
v->flag &= ~ME_HIDE;
- any_changed = 1;
+ any_changed = true;
}
if (!(v->flag & ME_HIDE))
- any_visible = 1;
+ any_visible = true;
}
if (any_changed) {
@@ -143,8 +144,9 @@ static void partialvis_update_grids(Object *ob,
CCGElem **grids;
CCGKey key;
BLI_bitmap **grid_hidden;
- int any_visible = 0;
- int *grid_indices, totgrid, any_changed, i;
+ int *grid_indices, totgrid, i;
+ bool any_changed = false, any_visible = false;
+
/* get PBVH data */
BKE_pbvh_node_get_grids(pbvh, node,
@@ -154,8 +156,7 @@ static void partialvis_update_grids(Object *ob,
BKE_pbvh_get_grid_key(pbvh, &key);
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
-
- any_changed = 0;
+
for (i = 0; i < totgrid; i++) {
int any_hidden = 0;
int g = grid_indices[i], x, y;
@@ -178,8 +179,8 @@ static void partialvis_update_grids(Object *ob,
* grid */
MEM_freeN(gh);
grid_hidden[g] = NULL;
- any_changed = 1;
- any_visible = 1;
+ any_changed = true;
+ any_visible = true;
continue;
}
@@ -195,14 +196,14 @@ static void partialvis_update_grids(Object *ob,
BLI_BITMAP_MODIFY(gh, y * key.grid_size + x,
action == PARTIALVIS_HIDE);
- any_changed = 1;
+ any_changed = true;
}
/* keep track of whether any elements are still hidden */
if (BLI_BITMAP_GET(gh, y * key.grid_size + x))
- any_hidden = 1;
+ any_hidden = true;
else
- any_visible = 1;
+ any_visible = true;
}
}
@@ -227,8 +228,8 @@ static void partialvis_update_bmesh_verts(BMesh *bm,
PartialVisAction action,
PartialVisArea area,
float planes[4][4],
- int *any_changed,
- int *any_visible)
+ bool *any_changed,
+ bool *any_visible)
{
GSetIterator gs_iter;
@@ -244,24 +245,24 @@ static void partialvis_update_bmesh_verts(BMesh *bm,
BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
else
BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
- (*any_changed) = TRUE;
+ (*any_changed) = true;
}
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
- (*any_visible) = TRUE;
+ (*any_visible) = true;
}
}
static void partialvis_update_bmesh(Object *ob,
- PBVH *pbvh,
- PBVHNode *node,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4])
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
{
BMesh *bm;
GSet *unique, *other;
- int any_changed = 0, any_visible = 0;
+ bool any_changed = false, any_visible = false;
bm = BKE_pbvh_get_bmesh(pbvh);
unique = BKE_pbvh_bmesh_node_unique_verts(node);
@@ -270,20 +271,20 @@ static void partialvis_update_bmesh(Object *ob,
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
partialvis_update_bmesh_verts(bm,
- unique,
- action,
- area,
- planes,
- &any_changed,
- &any_visible);
+ unique,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
partialvis_update_bmesh_verts(bm,
- other,
- action,
- area,
- planes,
- &any_changed,
- &any_visible);
+ other,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(node);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 003db8a9c43..47ca3e5ce0c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -238,7 +238,7 @@ void image_undo_remove_masks(void)
}
}
-void image_undo_restore(bContext *C, ListBase *lb)
+void ED_image_undo_restore(bContext *C, ListBase *lb)
{
Main *bmain = CTX_data_main(C);
Image *ima = NULL;
@@ -304,7 +304,7 @@ void image_undo_restore(bContext *C, ListBase *lb)
IMB_freeImBuf(tmpibuf);
}
-void image_undo_free(ListBase *lb)
+void ED_image_undo_free(ListBase *lb)
{
UndoImageTile *tile;
@@ -314,7 +314,7 @@ void image_undo_free(ListBase *lb)
/* Imagepaint Partial Redraw & Dirty Region */
-void imapaint_clear_partial_redraw(void)
+void ED_imapaint_clear_partial_redraw(void)
{
memset(&imapaintpartial, 0, sizeof(imapaintpartial));
}
@@ -331,7 +331,7 @@ void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int
*ty = (y >> IMAPAINT_TILE_BITS);
}
-void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
+void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
{
ImBuf *tmpibuf = NULL;
int tilex, tiley, tilew, tileh, tx, ty;
@@ -506,12 +506,12 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mou
}
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
- undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- image_undo_restore, image_undo_free);
+ ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ ED_image_undo_restore, ED_image_undo_free);
{
UnifiedPaintSettings *ups = &settings->unified_paint_settings;
- ups->draw_pressure = true;
+ ups->stroke_active = true;
}
return pop;
@@ -582,7 +582,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
paint_2d_stroke_done(pop->custom_paint);
}
- undo_paint_push_end(UNDO_PAINT_IMAGE);
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
/* duplicate warning, see texpaint_init */
#if 0
@@ -595,7 +595,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- ups->draw_pressure = false;
+ ups->stroke_active = false;
}
}
@@ -766,7 +766,7 @@ void brush_drawcursor_texpaint_uvsculpt(bContext *C, int x, int y, void *UNUSED(
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
/* hrmf, duplicate paint_draw_cursor logic here */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
+ if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
/* inner at full alpha */
glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size * ups->pressure_value, 40);
/* outer at half alpha */
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 1a19341acec..b2f429c31a1 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -49,6 +49,7 @@
#include "BKE_report.h"
#include "ED_screen.h"
+#include "ED_sculpt.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -275,6 +276,10 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
+ /* TODO(sergey): Support texture paint color space. */
+ if (!use_float) {
+ linearrgb_to_srgb_v3_v3(rgba, rgba);
+ }
mul_v3_v3(rgba, brush_rgb);
}
else {
@@ -362,6 +367,10 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
if (is_texbrush) {
brush_imbuf_tex_co(&tex_mapping, x, y, texco);
BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
+ /* TODO(sergey): Support texture paint color space. */
+ if (!use_float) {
+ linearrgb_to_srgb_v3_v3(rgba, rgba);
+ }
mul_v3_v3(rgba, brush_rgb);
}
else {
@@ -894,7 +903,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
/* blend into canvas */
for (a = 0; a < tot; a++) {
- imapaint_dirty_region(s->image, s->canvas,
+ ED_imapaint_dirty_region(s->image, s->canvas,
region[a].destx, region[a].desty,
region[a].width, region[a].height);
@@ -1103,7 +1112,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final)
ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
imapaint_image_update(s->sima, s->image, ibuf, false);
- imapaint_clear_partial_redraw();
+ ED_imapaint_clear_partial_redraw();
BKE_image_release_ibuf(s->image, ibuf, NULL);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 88cc954fb17..d6989c082a1 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3294,8 +3294,7 @@ static void project_paint_begin(ProjPaintState *ps)
projIma->ima = node->link;
projIma->touch = 0;
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ projIma->partRedrawRect = BLI_memarena_calloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
}
/* we have built the array, discard the linked list */
@@ -3344,8 +3343,7 @@ static void project_paint_end(ProjPaintState *ps)
for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) {
int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
- last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
- memset(last_projIma->undoRect, 0, size);
+ last_projIma->undoRect = (void **) BLI_memarena_calloc(arena, size);
last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
}
@@ -3760,8 +3758,9 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const
copy_v3_v3(rgb, ps->brush->rgb);
if (ps->is_texbrush) {
- /* XXX actually should convert texrgb from linear to srgb here */
mul_v3_v3(rgb, texrgb);
+ /* TODO(sergey): Support texture paint color space. */
+ linearrgb_to_srgb_v3_v3(rgb, rgb);
}
rgb_float_to_uchar(rgba_ub, rgb);
@@ -4414,8 +4413,8 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
- undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- image_undo_restore, image_undo_free);
+ ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ ED_image_undo_restore, ED_image_undo_free);
/* allocate and initialize spatial data structures */
project_paint_begin(&ps);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 5fff02f016b..01f5d53594e 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -146,13 +146,9 @@ int image_texture_paint_poll(struct bContext *C);
void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask);
void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
void image_undo_remove_masks(void);
-void image_undo_restore(struct bContext *C, struct ListBase *lb);
-void image_undo_free(struct ListBase *lb);
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
-void imapaint_clear_partial_redraw(void);
-void imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
@@ -232,13 +228,8 @@ typedef enum BrushStrokeMode {
} BrushStrokeMode;
/* paint_undo.c */
-typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
-typedef void (*UndoFreeCb)(struct ListBase *lb);
-
-void undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free);
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
-void undo_paint_push_end(int type);
/* paint_hide.c */
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 9b906c460e3..320bf4f0f5e 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -165,15 +165,15 @@ static int is_effected(float planes[4][4], const float co[3])
static void flip_plane(float out[4], const float in[4], const char symm)
{
- if (symm & SCULPT_SYMM_X)
+ if (symm & PAINT_SYMM_X)
out[0] = -in[0];
else
out[0] = in[0];
- if (symm & SCULPT_SYMM_Y)
+ if (symm & PAINT_SYMM_Y)
out[1] = -in[1];
else
out[1] = in[1];
- if (symm & SCULPT_SYMM_Z)
+ if (symm & PAINT_SYMM_Z)
out[2] = -in[2];
else
out[2] = in[2];
@@ -198,7 +198,7 @@ int do_sculpt_mask_box_select(ViewContext *vc, rcti *rect, bool select, bool UNU
PBVH *pbvh;
PBVHNode **nodes;
int totnode, i, symmpass;
- int symm = sd->flags & 7;
+ int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
mode = PAINT_MASK_FLOOD_VALUE;
value = select ? 1.0 : 0.0;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 397baeae4c9..0c28081723f 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -76,6 +76,7 @@ typedef struct PaintStroke {
ViewContext vc;
bglMats mats;
Brush *brush;
+ UnifiedPaintSettings *ups;
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
* to smooth the stroke */
@@ -174,7 +175,7 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
/* Truly temporary data that isn't stored in properties */
- ups->draw_pressure = TRUE;
+ ups->stroke_active = true;
ups->pressure_value = stroke->cached_pressure;
ups->pixel_radius = BKE_brush_size_get(scene, brush);
@@ -247,7 +248,7 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
else
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
- ups->draw_anchored = 1;
+ ups->draw_anchored = true;
}
else if (brush->flag & BRUSH_RAKE) {
if (!stroke->brush_init)
@@ -467,8 +468,10 @@ PaintStroke *paint_stroke_new(bContext *C,
StrokeDone done, int event_type)
{
PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
-
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
Brush *br = stroke->brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+
view3d_set_viewcontext(C, &stroke->vc);
if (stroke->vc.v3d)
view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats);
@@ -479,6 +482,7 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->redraw = redraw;
stroke->done = done;
stroke->event_type = event_type; /* for modal, return event */
+ stroke->ups = ups;
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
@@ -498,6 +502,14 @@ void paint_stroke_data_free(struct wmOperator *op)
static void stroke_done(struct bContext *C, struct wmOperator *op)
{
struct PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
+
+ ups->draw_anchored = false;
+ ups->stroke_active = false;
+
+ /* reset rotation here to avoid doing so in cursor display */
+ if (!(stroke->brush->flag & BRUSH_RAKE))
+ ups->brush_rotation = 0.0f;
if (stroke->stroke_started) {
if (stroke->redraw)
@@ -556,7 +568,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
{
if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
(br->flag & BRUSH_ANCHORED) ||
- (br->flag & BRUSH_RESTORE_MESH))
+ (br->flag & BRUSH_DRAG_DOT))
{
return false;
}
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index 50a79005ee3..b4bd46376d3 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -223,7 +223,7 @@ static void undo_stack_free(UndoStack *stack)
/* Exported Functions */
-void undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free)
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free)
{
if (type == UNDO_PAINT_IMAGE)
undo_stack_push_begin(&ImageUndoStack, name, restore, free);
@@ -253,7 +253,7 @@ void undo_paint_push_count_alloc(int type, int size)
MeshUndoStack.current->undosize += size;
}
-void undo_paint_push_end(int type)
+void ED_undo_paint_push_end(int type)
{
if (type == UNDO_PAINT_IMAGE)
undo_stack_push_end(&ImageUndoStack);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 714d67c8039..9d7bad2591e 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1088,7 +1088,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
ViewContext vc;
Mesh *me;
- short change = FALSE;
+ bool changed = false;
view3d_set_viewcontext(C, &vc);
me = BKE_mesh_from_object(vc.obact);
@@ -1122,11 +1122,11 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
const int vgroup_active = vc.obact->actdef - 1;
float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
- change = TRUE;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
/* not really correct since the brush didnt change, but redraws the toolbar */
WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL); /* ts->wpaint->paint.brush */
@@ -1468,14 +1468,14 @@ static float redistribute_change(MDeformVert *ndv, const int defbase_tot,
float totchange, float total_valid,
char do_auto_normalize)
{
- float was_change;
+ bool changed;
float change;
float oldval;
MDeformWeight *ndw;
int i;
do {
/* assume there is no change until you see one */
- was_change = FALSE;
+ changed = false;
/* change each group by the same amount each time */
change = totchange / total_valid;
for (i = 0; i < ndv->totweight && total_valid && totchange; i++) {
@@ -1507,14 +1507,14 @@ static float redistribute_change(MDeformVert *ndv, const int defbase_tot,
}
/* see if there was a change */
if (oldval != ndw->weight) {
- was_change = TRUE;
+ changed = true;
}
}
}
}
/* don't go again if there was no change, if there is no valid group,
* or there is no change left */
- } while (was_change && total_valid && totchange);
+ } while (changed && total_valid && totchange);
/* left overs */
return totchange;
}
@@ -2255,11 +2255,6 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU
if (me->editflag & ME_EDIT_MIRROR_X) {
wpd->vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, wpd->vgroup_active);
}
-
- {
- UnifiedPaintSettings *ups = &ts->unified_paint_settings;
- ups->draw_pressure = true;
- }
return TRUE;
}
@@ -2366,12 +2361,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
else totindex = 0;
}
- if (use_face_sel && me->mpoly) {
+ if (use_face_sel && me->totpoly) {
+ MPoly *mpoly = me->mpoly;
for (index = 0; index < totindex; index++) {
if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
+ MPoly *mp = &mpoly[indexar[index] - 1];
- if ((mpoly->flag & ME_FACE_SEL) == 0) {
+ if ((mp->flag & ME_FACE_SEL) == 0) {
indexar[index] = 0;
}
}
@@ -2552,11 +2548,6 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
}
}
- {
- UnifiedPaintSettings *ups = &ts->unified_paint_settings;
- ups->draw_pressure = false;
- }
-
DAG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -2874,11 +2865,6 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl
invert_m4_m4(imat, mat);
copy_m3_m4(vpd->vpimat, imat);
- {
- UnifiedPaintSettings *ups = &ts->unified_paint_settings;
- ups->draw_pressure = true;
- }
-
return 1;
}
@@ -3102,11 +3088,6 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
if (vpd->mfacetag)
MEM_freeN(vpd->mfacetag);
- {
- UnifiedPaintSettings *ups = &ts->unified_paint_settings;
- ups->draw_pressure = false;
- }
-
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
MEM_freeN(vpd);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 6bd935af436..fa938eca487 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -418,7 +418,7 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
/* Requires mesh restore, which doesn't work with
* dynamic-topology */
!(brush->flag & BRUSH_ANCHORED) &&
- !(brush->flag & BRUSH_RESTORE_MESH) &&
+ !(brush->flag & BRUSH_DRAG_DOT) &&
(!ELEM6(brush->sculpt_tool,
/* These brushes, as currently coded, cannot
@@ -762,15 +762,15 @@ static float integrate_overlap(Brush *br)
/* Uses symm to selectively flip any axis of a coordinate. */
static void flip_v3_v3(float out[3], const float in[3], const char symm)
{
- if (symm & SCULPT_SYMM_X)
+ if (symm & PAINT_SYMM_X)
out[0] = -in[0];
else
out[0] = in[0];
- if (symm & SCULPT_SYMM_Y)
+ if (symm & PAINT_SYMM_Y)
out[1] = -in[1];
else
out[1] = in[1];
- if (symm & SCULPT_SYMM_Z)
+ if (symm & PAINT_SYMM_Z)
out[2] = -in[2];
else
out[2] = in[2];
@@ -820,7 +820,7 @@ static float calc_radial_symmetry_feather(Sculpt *sd, StrokeCache *cache, const
static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
{
- if (sd->flags & SCULPT_SYMMETRY_FEATHER) {
+ if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
float overlap;
int symm = cache->symmetry;
int i;
@@ -3076,9 +3076,12 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
/* Only act if some verts are inside the brush area */
if (totnode) {
- PBVHTopologyUpdateMode mode = PBVH_Subdivide;
+ PBVHTopologyUpdateMode mode = 0;
float location[3];
+ if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE)
+ mode |= PBVH_Subdivide;
+
if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) ||
(brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY))
{
@@ -3464,7 +3467,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
- const char symm = sd->flags & 7;
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
int i;
float feather = calc_symmetry_feather(sd, ss->cache);
@@ -4012,7 +4015,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
/* location stays the same for finding vertices in brush radius */
copy_v3_v3(cache->true_location, cache->orig_grab_location);
- ups->draw_anchored = 1;
+ ups->draw_anchored = true;
copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
ups->anchored_size = ups->pixel_radius;
}
@@ -4139,7 +4142,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
#undef PIXEL_INPUT_THRESHHOLD
}
- ups->draw_anchored = 1;
+ ups->draw_anchored = true;
copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
copy_v3_v3(cache->anchored_location, cache->true_location);
ups->anchored_size = ups->pixel_radius;
@@ -4311,7 +4314,7 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
if ((brush->flag & BRUSH_ANCHORED) ||
(brush->sculpt_tool == SCULPT_TOOL_GRAB &&
BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
- (brush->flag & BRUSH_RESTORE_MESH))
+ (brush->flag & BRUSH_DRAG_DOT))
{
paint_mesh_restore_co(sd, ob);
}
@@ -4453,7 +4456,6 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
{
- UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
SculptSession *ss = ob->sculpt;
@@ -4461,10 +4463,6 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_omp_done(ss);
- /* reset values used to draw brush after completing the stroke */
- ups->draw_anchored = 0;
- ups->draw_pressure = 0;
-
/* Finished */
if (ss->cache) {
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -5065,7 +5063,10 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ts->sculpt = MEM_callocN(sizeof(Sculpt), "sculpt mode data");
/* Turn on X plane mirror symmetry by default */
- ts->sculpt->flags |= SCULPT_SYMM_X;
+ ts->sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
+
+ /* Make sure at least dyntopo subdivision is enabled */
+ ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE;
}
if (!ts->sculpt->detail_size)
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 8861777f326..846801ae85d 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -819,7 +819,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
- undo_paint_push_begin(UNDO_PAINT_MESH, name,
+ ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
sculpt_undo_restore, sculpt_undo_free);
}
@@ -839,5 +839,5 @@ void sculpt_undo_push_end(void)
BKE_pbvh_node_layer_disp_free(unode->node);
}
- undo_paint_push_end(UNDO_PAINT_MESH);
+ ED_undo_paint_push_end(UNDO_PAINT_MESH);
}
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 7c9d867aad6..aafbc6af558 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -780,11 +780,12 @@ void ACTION_OT_duplicate(wmOperatorType *ot)
/* ******************** Delete Keyframes Operator ************************* */
-static void delete_action_keys(bAnimContext *ac)
+static bool delete_action_keys(bAnimContext *ac)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ bool changed = false;
/* filter data */
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
@@ -796,17 +797,17 @@ static void delete_action_keys(bAnimContext *ac)
/* loop through filtered data and delete selected keys */
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frames_delete((bGPDlayer *)ale->data);
+ changed |= ED_gplayer_frames_delete((bGPDlayer *)ale->data);
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_frames_delete((MaskLayer *)ale->data);
+ changed |= ED_masklayer_frames_delete((MaskLayer *)ale->data);
}
else {
FCurve *fcu = (FCurve *)ale->key_data;
AnimData *adt = ale->adt;
/* delete selected keyframes only */
- delete_fcurve_keys(fcu);
+ changed |= delete_fcurve_keys(fcu);
/* Only delete curve too if it won't be doing anything anymore */
if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
@@ -816,20 +817,23 @@ static void delete_action_keys(bAnimContext *ac)
/* free filtered list */
BLI_freelistN(&anim_data);
+
+ return changed;
}
/* ------------------- */
-static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
+static int actkeys_delete_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ bool changed;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* delete keyframes */
- delete_action_keys(&ac);
+ changed = delete_action_keys(&ac);
/* validate keyframes after editing */
if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
@@ -838,6 +842,9 @@ static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ if (changed)
+ BKE_report(op->reports, RPT_INFO, "Deleted selected keyframes");
+
return OPERATOR_FINISHED;
}
@@ -849,7 +856,6 @@ void ACTION_OT_delete(wmOperatorType *ot)
ot->description = "Remove all selected keyframes";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = actkeys_delete_exec;
ot->poll = ED_operator_action_active;
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index d62dd88418f..c256dbb3b59 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -305,7 +305,8 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
bAnimContext ac;
rcti rect;
short mode = 0, selectmode = 0;
- int gesture_mode, extend;
+ int gesture_mode;
+ bool extend;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 8508123f942..975123f244c 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -516,7 +516,7 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS
if (!last_category || strcmp(last_category, user->category) != 0) {
uiItemL(layout, user->category, ICON_NONE);
but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
+ but->drawflag = UI_BUT_TEXT_LEFT;
}
/* create button */
@@ -577,7 +577,7 @@ void uiTemplateTextureUser(uiLayout *layout, bContext *C)
/* some cosmetic tweaks */
but->type = MENU;
- but->flag |= UI_TEXT_LEFT;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
but->flag &= ~UI_ICON_SUBMENU;
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 059b8ace7b9..e85b055bc59 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -341,7 +341,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
else
UI_ThemeColor(TH_TEXT);
- font_height = BLF_height(fontid, channel->name);
+ font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
y - font_height / 2.0f, 0.0f);
BLF_draw(fontid, channel->name, strlen(channel->name));
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index e5cd7247c43..0fbed2c3c1e 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -96,7 +96,7 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op)
MovieTrackingDopesheetChannel *channel;
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
float location[2];
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
int current_channel_index = 0, channel_index;
RNA_float_get_array(op->ptr, "location", location);
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 3c9eb1fe79e..79607163913 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -48,6 +48,7 @@
#include "BLI_math_base.h"
#include "BKE_context.h"
+#include "BKE_image.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
@@ -86,7 +87,7 @@ void clip_draw_curfra_label(const int framenr, const float x, const float y)
BLF_size(fontid, 11.0f, U.dpi);
BLI_snprintf(numstr, sizeof(numstr), "%d", framenr);
- BLF_width_and_height(fontid, numstr, &font_dims[0], &font_dims[1]);
+ BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
@@ -1038,12 +1039,129 @@ static void getArrowEndPoint(const int width, const int height, const float zoom
add_v2_v2v2(end_point, start_corner, direction);
}
-static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+static void homogeneous_2d_to_gl_matrix(/*const*/ float matrix[3][3],
+ float gl_matrix[4][4])
+{
+ gl_matrix[0][0] = matrix[0][0];
+ gl_matrix[0][1] = matrix[0][1];
+ gl_matrix[0][2] = 0.0f;
+ gl_matrix[0][3] = matrix[0][2];
+
+ gl_matrix[1][0] = matrix[1][0];
+ gl_matrix[1][1] = matrix[1][1];
+ gl_matrix[1][2] = 0.0f;
+ gl_matrix[1][3] = matrix[1][2];
+
+ gl_matrix[2][0] = 0.0f;
+ gl_matrix[2][1] = 0.0f;
+ gl_matrix[2][2] = 1.0f;
+ gl_matrix[2][3] = 0.0f;
+
+ gl_matrix[3][0] = matrix[2][0];
+ gl_matrix[3][1] = matrix[2][1];
+ gl_matrix[3][2] = 0.0f;
+ gl_matrix[3][3] = matrix[2][2];
+}
+
+static void draw_plane_marker_image(Scene *scene,
+ MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker)
+{
+ Image *image = plane_track->image;
+ ImBuf *ibuf;
+ void *lock;
+
+ if (image == NULL) {
+ return;
+ }
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+ if (ibuf) {
+ unsigned char *display_buffer;
+ void *cache_handle;
+
+ if (image->flag & IMA_VIEW_AS_RENDER) {
+ display_buffer = IMB_display_buffer_acquire(ibuf,
+ &scene->view_settings,
+ &scene->display_settings,
+ &cache_handle);
+ }
+ else {
+ display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
+ &scene->display_settings,
+ &cache_handle);
+ }
+
+ if (display_buffer) {
+ GLuint texid, last_texid;
+ float frame_corners[4][2] = {{0.0f, 0.0f},
+ {1.0f, 0.0f},
+ {1.0f, 1.0f},
+ {0.0f, 1.0f}};
+ float perspective_matrix[3][3];
+ float gl_matrix[4][4];
+ bool transparent = false;
+ BKE_tracking_homography_between_two_quads(frame_corners,
+ plane_marker->corners,
+ perspective_matrix);
+
+ homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
+
+ if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
+ transparent = true;
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
+
+ last_texid = glaGetOneInteger(GL_TEXTURE_2D);
+ glEnable(GL_TEXTURE_2D);
+ glGenTextures(1, (GLuint *)&texid);
+
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, display_buffer);
+
+ glPushMatrix();
+ glMultMatrixf(gl_matrix);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
+ glEnd();
+
+ glPopMatrix();
+
+ glBindTexture(GL_TEXTURE_2D, last_texid);
+ glDisable(GL_TEXTURE_2D);
+
+ if (transparent) {
+ glDisable(GL_BLEND);
+ }
+ }
+
+ IMB_display_buffer_release(cache_handle);
+ }
+
+ BKE_image_release_ibuf(image, ibuf, lock);
+}
+
+static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
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 draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f;
float px[2];
if (draw_outline) {
@@ -1063,6 +1181,11 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
+ /* Draw image */
+ if (draw_outline == false) {
+ draw_plane_marker_image(scene, plane_track, plane_marker);
+ }
+
if (draw_outline) {
if (!tiny) {
glLineWidth(3.0f);
@@ -1073,34 +1196,36 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t
glEnable(GL_LINE_STIPPLE);
}
- /* Draw rectangle itself. */
- glBegin(GL_LINE_LOOP);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(plane_marker->corners[1]);
- glVertex2fv(plane_marker->corners[2]);
- glVertex2fv(plane_marker->corners[3]);
- glEnd();
-
- /* Draw axis. */
- if (!draw_outline) {
- float end_point[2];
- glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
-
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
- glColor3f(1.0, 0.0, 0.0f);
- glBegin(GL_LINES);
+ if (draw_plane_quad) {
+ /* Draw rectangle itself. */
+ glBegin(GL_LINE_LOOP);
glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
+ glVertex2fv(plane_marker->corners[1]);
+ glVertex2fv(plane_marker->corners[2]);
+ glVertex2fv(plane_marker->corners[3]);
glEnd();
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
- glColor3f(0.0, 1.0, 0.0f);
- glBegin(GL_LINES);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
- glEnd();
+ /* Draw axis. */
+ if (!draw_outline) {
+ float end_point[2];
+ glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+ glColor3f(1.0, 0.0, 0.0f);
+ glBegin(GL_LINES);
+ glVertex2fv(plane_marker->corners[0]);
+ glVertex2fv(end_point);
+ glEnd();
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+ glColor3f(0.0, 1.0, 0.0f);
+ glBegin(GL_LINES);
+ glVertex2fv(plane_marker->corners[0]);
+ glVertex2fv(end_point);
+ glEnd();
- glPopAttrib();
+ glPopAttrib();
+ }
}
/* Draw sliders. */
@@ -1122,32 +1247,32 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t
}
}
-static void draw_plane_marker_outline(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+static void draw_plane_marker_outline(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
MovieTrackingPlaneMarker *plane_marker, int width, int height)
{
- draw_plane_marker_ex(sc, plane_track, plane_marker, false, true, width, height);
+ draw_plane_marker_ex(sc, scene, plane_track, plane_marker, false, true, width, height);
}
-static void draw_plane_marker(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+static void draw_plane_marker(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
int width, int height)
{
- draw_plane_marker_ex(sc, plane_track, plane_marker, is_active_track, false, width, height);
+ draw_plane_marker_ex(sc, scene, plane_track, plane_marker, is_active_track, false, width, height);
}
-static void draw_plane_track(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+static void draw_plane_track(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
int framenr, bool is_active_track, int width, int height)
{
MovieTrackingPlaneMarker *plane_marker;
plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
- draw_plane_marker_outline(sc, plane_track, plane_marker, width, height);
- draw_plane_marker(sc, plane_track, plane_marker, is_active_track, width, height);
+ draw_plane_marker_outline(sc, scene, plane_track, plane_marker, width, height);
+ draw_plane_marker(sc, scene, plane_track, plane_marker, is_active_track, width, height);
}
/* Draw all kind of tracks. */
-static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
+static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
int width, int height, float zoomx, float zoomy)
{
float x, y;
@@ -1180,6 +1305,15 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
act_track = BKE_tracking_track_get_active(tracking);
+ /* Draw plane tracks */
+ active_plane_track = BKE_tracking_plane_track_get_active(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
+ }
+
if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
int count = 0;
@@ -1348,15 +1482,6 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
glDisable(GL_POINT_SMOOTH);
}
- /* Draw plane tracks */
- active_plane_track = BKE_tracking_plane_track_get_active(tracking);
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- draw_plane_track(sc, plane_track, framenr, plane_track == active_plane_track, width, height);
- }
-
glPopMatrix();
if (sc->flag & SC_SHOW_NAMES) {
@@ -1666,7 +1791,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
if (width && height) {
draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
- draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy);
+ draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy);
draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
}
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index d1c44693995..ffb805cdc5f 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -43,6 +43,7 @@
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "BKE_depsgraph.h"
+#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -319,7 +320,7 @@ void CLIP_OT_graph_select(wmOperatorType *ot)
typedef struct BorderSelectuserData {
rctf rect;
int mode;
- bool change, extend;
+ bool changed, extend;
} BorderSelectuserData;
static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
@@ -340,7 +341,7 @@ static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
else
marker->flag &= ~flag;
- data->change = TRUE;
+ data->changed = true;
}
else if (!data->extend) {
marker->flag &= ~MARKER_GRAPH_SEL;
@@ -368,13 +369,13 @@ static int border_select_graph_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &userdata.rect.xmin, &userdata.rect.ymin);
UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &userdata.rect.xmax, &userdata.rect.ymax);
- userdata.change = false;
+ userdata.changed = false;
userdata.mode = RNA_int_get(op->ptr, "gesture_mode");
userdata.extend = RNA_boolean_get(op->ptr, "extend");
clip_graph_tracking_values_iterate_track(sc, act_track, &userdata, border_select_cb, NULL, NULL);
- if (userdata.change) {
+ if (userdata.changed) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
return OPERATOR_FINISHED;
@@ -471,16 +472,19 @@ void CLIP_OT_graph_select_all_markers(wmOperatorType *ot)
/******************** delete curve operator ********************/
-static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
+static int delete_curve_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- if (act_track)
+ if (act_track) {
clip_delete_track(C, clip, act_track);
+ BKE_report(op->reports, RPT_INFO, "Deleted track");
+ }
+
return OPERATOR_FINISHED;
}
@@ -488,11 +492,10 @@ void CLIP_OT_graph_delete_curve(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Curve";
- ot->description = "Delete selected curves";
+ ot->description = "Delete track corresponding to the selected curve";
ot->idname = "CLIP_OT_graph_delete_curve";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = delete_curve_exec;
ot->poll = ED_space_clip_tracking_poll;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 5607d7dc635..b198b68b95a 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -234,7 +234,7 @@ void CLIP_OT_add_marker_at_click(wmOperatorType *ot)
/********************** delete track operator *********************/
-static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
+static int delete_track_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -243,7 +243,7 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *track = tracksbase->first, *next;
MovieTrackingPlaneTrack *plane_track, *next_plane_track;
- bool modified = false;
+ bool changed = false;
/* Delete selected plane tracks. */
for (plane_track = plane_tracks_base->first;
@@ -255,7 +255,7 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
if (plane_track->flag & SELECT) {
BKE_tracking_plane_track_free(plane_track);
BLI_freelinkN(plane_tracks_base, plane_track);
- modified = true;
+ changed = true;
}
}
@@ -263,8 +263,10 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
while (track) {
next = track->next;
- if (TRACK_VIEW_SELECTED(sc, track))
+ if (TRACK_VIEW_SELECTED(sc, track)) {
clip_delete_track(C, clip, track);
+ changed = true;
+ }
track = next;
}
@@ -272,7 +274,8 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
/* nothing selected now, unlock view so it can be scrolled nice again */
sc->flag &= ~SC_LOCK_SELECTION;
- if (modified) {
+ if (changed) {
+ BKE_report(op->reports, RPT_INFO, "Deleted selected tracks");
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
}
@@ -287,7 +290,6 @@ void CLIP_OT_delete_track(wmOperatorType *ot)
ot->description = "Delete selected tracks";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = delete_track_exec;
ot->poll = ED_space_clip_tracking_poll;
@@ -297,7 +299,7 @@ void CLIP_OT_delete_track(wmOperatorType *ot)
/********************** delete marker operator *********************/
-static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
+static int delete_marker_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -307,6 +309,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
MovieTrackingPlaneTrack *plane_track, *plane_track_next;
int framenr = ED_space_clip_get_clip_frame_number(sc);
int has_selection = 0;
+ bool changed = false;
while (track) {
next = track->next;
@@ -318,6 +321,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
has_selection |= track->markersnr > 1;
clip_delete_marker(C, clip, track, marker);
+ changed = true;
}
}
@@ -341,6 +345,8 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
else {
BKE_tracking_plane_marker_delete(plane_track, framenr);
}
+
+ changed = true;
}
}
}
@@ -350,6 +356,11 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
sc->flag &= ~SC_LOCK_SELECTION;
}
+ if (!changed)
+ return OPERATOR_CANCELLED;
+
+ BKE_report(op->reports, RPT_INFO, "Deleted markers for current frame from selected tracks");
+
return OPERATOR_FINISHED;
}
@@ -361,7 +372,6 @@ void CLIP_OT_delete_marker(wmOperatorType *ot)
ot->description = "Delete marker for current frame from selected tracks";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = delete_marker_exec;
ot->poll = ED_space_clip_tracking_poll;
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 7cb5f9b5dc0..65b7a5dee65 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -402,7 +402,7 @@ static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
float co[2];
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
if (!extend) {
MovieTrackingTrack *track = tracking_marker_check_slide(C, event, NULL, NULL, NULL);
@@ -461,7 +461,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
rctf rectf;
- bool change = false;
+ bool changed = false;
int mode, extend;
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -491,7 +491,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = true;
+ changed = true;
}
}
@@ -521,11 +521,11 @@ static int border_select_exec(bContext *C, wmOperator *op)
}
}
- change = true;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
BKE_tracking_dopesheet_tag_update(tracking);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
@@ -570,7 +570,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
- bool change = false;
+ bool changed = false;
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
@@ -597,7 +597,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = true;
+ changed = true;
}
}
@@ -631,17 +631,17 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
}
}
- change = true;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
BKE_tracking_dopesheet_tag_update(tracking);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
}
- return change;
+ return changed;
}
static int clip_lasso_select_exec(bContext *C, wmOperator *op)
@@ -715,7 +715,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
int x, y, radius, width, height, mode;
- bool change = false;
+ bool changed = false;
float zoomx, zoomy, offset[2], ellipse[2];
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -747,7 +747,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
else
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- change = true;
+ changed = true;
}
}
@@ -774,11 +774,11 @@ static int circle_select_exec(bContext *C, wmOperator *op)
}
}
- change = true;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
BKE_tracking_dopesheet_tag_update(tracking);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index c4e6ca97418..e31d813fc5e 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -75,25 +75,6 @@
#include "file_intern.h" // own include
-/* button events */
-enum {
- B_FS_DIRNAME,
- B_FS_FILENAME
-} /*eFile_ButEvents*/;
-
-
-static void do_file_buttons(bContext *C, void *UNUSED(arg), int event)
-{
- switch (event) {
- case B_FS_FILENAME:
- file_filename_exec(C, NULL);
- break;
- case B_FS_DIRNAME:
- file_directory_exec(C, NULL);
- break;
- }
-}
-
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
* The controls are laid out as follows:
*
@@ -139,7 +120,6 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
/* Initialize UI block. */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
block = uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS);
- uiBlockSetHandleFunc(block, do_file_buttons, NULL);
/* exception to make space for collapsed region icon */
for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
@@ -180,21 +160,31 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
/* callbacks for operator check functions */
uiBlockSetFunc(block, file_draw_check_cb, NULL, NULL);
- but = uiDefButTextO(block, TEX, "FILE_OT_directory", 0, "",
- min_x, line1_y, line1_w - chan_offs, btn_h,
- params->dir, 0.0, (float)FILE_MAX, 0, 0,
- TIP_("File path"));
+ but = uiDefBut(block, TEX, -1, "",
+ min_x, line1_y, line1_w - chan_offs, btn_h,
+ params->dir, 0.0, (float)FILE_MAX, 0, 0,
+ TIP_("File path"));
uiButSetCompleteFunc(but, autocomplete_directory, NULL);
uiButSetFlag(but, UI_BUT_NO_UTF8);
+ uiButClearFlag(but, UI_BUT_UNDO);
+ uiButSetNFunc(but, file_directory_enter_handle, NULL, but);
+
+ /* TODO, directory editing is non-functional while a library is loaded
+ * until this is properly supported just disable it. */
+ if (sfile->files && filelist_lib(sfile->files))
+ uiButSetFlag(but, UI_BUT_DISABLED);
if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
- but = uiDefBut(block, TEX, B_FS_FILENAME, "",
+ but = uiDefBut(block, TEX, -1, "",
min_x, line2_y, line2_w - chan_offs, btn_h,
params->file, 0.0, (float)FILE_MAXFILE, 0, 0,
TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
uiButSetCompleteFunc(but, autocomplete_file, NULL);
uiButSetFlag(but, UI_BUT_NO_UTF8);
- uiButClearFlag(but, UI_BUT_UNDO); /* operator button above does this automatic */
+ uiButClearFlag(but, UI_BUT_UNDO);
+ /* silly workaround calling NFunc to ensure this does not get called
+ * immediate ui_apply_but_func but only after button deactivates */
+ uiButSetNFunc(but, file_filename_enter_handle, NULL, but);
/* check if this overrides a file and if the operator option is used */
if (overwrite_alert) {
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index d01286442be..841cb0d5f77 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -72,7 +72,6 @@ void FILE_OT_execute(struct wmOperatorType *ot);
void FILE_OT_cancel(struct wmOperatorType *ot);
void FILE_OT_parent(struct wmOperatorType *ot);
void FILE_OT_directory_new(struct wmOperatorType *ot);
-void FILE_OT_directory(struct wmOperatorType *ot);
void FILE_OT_previous(struct wmOperatorType *ot);
void FILE_OT_next(struct wmOperatorType *ot);
void FILE_OT_refresh(struct wmOperatorType *ot);
@@ -87,11 +86,12 @@ int file_cancel_exec(bContext *C, struct wmOperator *unused);
int file_parent_exec(bContext *C, struct wmOperator *unused);
int file_previous_exec(bContext *C, struct wmOperator *unused);
int file_next_exec(bContext *C, struct wmOperator *unused);
-int file_filename_exec(bContext *C, struct wmOperator *unused);
-int file_directory_exec(bContext *C, struct wmOperator *unused);
int file_directory_new_exec(bContext *C, struct wmOperator *unused);
int file_delete_exec(bContext *C, struct wmOperator *unused);
+void file_directory_enter_handle(bContext *C, void *arg_unused, void *arg_but);
+void file_filename_enter_handle(bContext *C, void *arg_unused, void *arg_but);
+
int file_highlight_set(struct SpaceFile *sfile, struct ARegion *ar, int mx, int my);
void file_sfile_to_operator(struct wmOperator *op, struct SpaceFile *sfile, char *filepath);
@@ -105,8 +105,8 @@ float file_string_width(const char *str);
float file_font_pointsize(void);
void file_change_dir(bContext *C, int checkdir);
int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file);
-bool autocomplete_directory(struct bContext *C, char *str, void *arg_v);
-bool autocomplete_file(struct bContext *C, char *str, void *arg_v);
+int autocomplete_directory(struct bContext *C, char *str, void *arg_v);
+int autocomplete_file(struct bContext *C, char *str, void *arg_v);
/* file_panels.c */
void file_panels_register(struct ARegionType *art);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index a97b3b1d719..f4cae0c462f 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -32,6 +32,8 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLO_readfile.h"
+
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
@@ -45,6 +47,8 @@
#include "ED_screen.h"
#include "ED_fileselect.h"
+#include "UI_interface.h"
+
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
@@ -270,8 +274,8 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
rcti rect;
FileSelect ret;
- int extend = RNA_boolean_get(op->ptr, "extend");
- short select = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
+ const bool select = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
WM_operator_properties_border_to_rcti(op, &rect);
@@ -317,9 +321,9 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelect ret;
rcti rect;
- int extend = RNA_boolean_get(op->ptr, "extend");
- int fill = RNA_boolean_get(op->ptr, "fill");
- int do_diropen = RNA_boolean_get(op->ptr, "open");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool fill = RNA_boolean_get(op->ptr, "fill");
+ const bool do_diropen = RNA_boolean_get(op->ptr, "open");
if (ar->regiontype != RGN_TYPE_WINDOW)
return OPERATOR_CANCELLED;
@@ -1131,6 +1135,12 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
/* reload dir to make sure we're seeing what's in the directory */
ED_fileselect_clear(wm, sfile);
+
+ if (RNA_boolean_get(op->ptr, "open")) {
+ BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir));
+ file_change_dir(C, 1);
+ }
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
@@ -1153,7 +1163,8 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
prop = RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
+ prop = RNA_def_boolean(ot->srna, "open", false, "Open", "Open new directory");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
@@ -1194,36 +1205,13 @@ static void file_expand_directory(bContext *C)
}
}
-static int file_directory_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- SpaceFile *sfile = CTX_wm_space_file(C);
-
- if (sfile->params) {
- file_expand_directory(C);
-
- if (!BLI_exists(sfile->params->dir)) {
- return WM_operator_confirm_message(C, op, "Create new directory?");
- }
-
- return file_directory_exec(C, op);
- }
-
- return OPERATOR_CANCELLED;
-}
-
-
-
-int file_directory_exec(bContext *C, wmOperator *UNUSED(unused))
+void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UNUSED(arg_but))
{
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile->params) {
file_expand_directory(C);
- if (!BLI_exists(sfile->params->dir)) {
- BLI_dir_create_recursive(sfile->params->dir);
- }
-
/* special case, user may have pasted a filepath into the directory */
if (BLI_is_file(sfile->params->dir)) {
char path[sizeof(sfile->params->dir)];
@@ -1232,21 +1220,53 @@ int file_directory_exec(bContext *C, wmOperator *UNUSED(unused))
}
BLI_cleanup_dir(G.main->name, sfile->params->dir);
- file_change_dir(C, 1);
+
+ if (BLI_exists(sfile->params->dir)) {
+ /* if directory exists, enter it immediately */
+ file_change_dir(C, 1);
+
+ /* don't do for now because it selects entire text instead of
+ * placing cursor at the end */
+ /* UI_textbutton_activate_but(C, but); */
+ }
+ else {
+ const char *lastdir = folderlist_peeklastdir(sfile->folders_prev);
+
+ /* if not, ask to create it and enter if confirmed */
+ PointerRNA ptr;
+ WM_operator_properties_create(&ptr, "FILE_OT_directory_new");
+ RNA_string_set(&ptr, "directory", sfile->params->dir);
+ RNA_boolean_set(&ptr, "open", true);
+
+ if (lastdir)
+ BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir));
+
+
+ WM_operator_name_call(C, "FILE_OT_directory_new", WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ }
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-
- return OPERATOR_FINISHED;
}
-int file_filename_exec(bContext *C, wmOperator *UNUSED(unused))
+void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg_but)
{
SpaceFile *sfile = CTX_wm_space_file(C);
+ uiBut *but = arg_but;
char matched_file[FILE_MAX];
+ char filepath[sizeof(sfile->params->dir)];
+
if (sfile->params) {
+ int matches;
matched_file[0] = '\0';
- if (file_select_match(sfile, sfile->params->file, matched_file)) {
+ filepath[0] = '\0';
+
+ file_expand_directory(C);
+
+ matches = file_select_match(sfile, sfile->params->file, matched_file);
+
+ if (matches) {
/* int i, numfiles = filelist_numfiles(sfile->files); */ /* XXX UNUSED */
sfile->params->file[0] = '\0';
/* replace the pattern (or filename that the user typed in, with the first selected file of the match */
@@ -1254,31 +1274,34 @@ int file_filename_exec(bContext *C, wmOperator *UNUSED(unused))
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
- }
- return OPERATOR_FINISHED;
-}
+ if (matches == 1) {
-/* TODO, directory operator is non-functional while a library is loaded
- * until this is properly supported just disable it. */
-static int file_directory_poll(bContext *C)
-{
- /* sfile->files can be NULL on file load */
- SpaceFile *sfile = CTX_wm_space_file(C);
- return ED_operator_file_active(C) && (sfile->files == NULL || filelist_lib(sfile->files) == NULL);
-}
+ BLI_join_dirfile(filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file);
-void FILE_OT_directory(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Enter Directory Name";
- ot->description = "Enter a directory name";
- ot->idname = "FILE_OT_directory";
-
- /* api callbacks */
- ot->invoke = file_directory_invoke;
- ot->exec = file_directory_exec;
- ot->poll = file_directory_poll; /* <- important, handler is on window level */
+ /* if directory, open it and empty filename field */
+ if (BLI_is_dir(filepath)) {
+ BLI_cleanup_dir(G.main->name, filepath);
+ BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
+ sfile->params->file[0] = '\0';
+ file_change_dir(C, 1);
+ UI_textbutton_activate_but(C, but);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
+ else if (sfile->params->type == FILE_LOADLIB) {
+ char tdir[FILE_MAX], tgroup[FILE_MAX];
+ BLI_add_slash(filepath);
+ if (BLO_is_a_library(filepath, tdir, tgroup)) {
+ BLI_cleanup_dir(G.main->name, filepath);
+ BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir));
+ sfile->params->file[0] = '\0';
+ file_change_dir(C, 0);
+ UI_textbutton_activate_but(C, but);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ }
+ }
+ }
+ }
}
void FILE_OT_refresh(struct wmOperatorType *ot)
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index f4161c7da1c..1809c6cb835 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -116,7 +116,7 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat
but = uiDefIconTextButS(block, LISTROW, 0, icon, dir, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, nr, 0, i, 0, 0, entry);
uiButSetFunc(but, file_panel_cb, entry, NULL);
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- uiButSetFlag(but, UI_ICON_LEFT | UI_TEXT_LEFT);
+ uiButSetDrawFlag(but, UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT);
/* create delete button */
if (allow_delete && fsmenu_can_save(fsmenu, category, i)) {
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index a2f81498dd3..872960432d9 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -479,6 +479,17 @@ void folderlist_pushdir(ListBase *folderlist, const char *dir)
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;
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index d093d427eae..eb99b0d21ab 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -98,6 +98,7 @@ 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 thumbnails_start(struct FileList *filelist, const struct bContext *C);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index c6e1541352d..d329d505138 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -435,7 +435,7 @@ float file_string_width(const char *str)
{
uiStyle *style = UI_GetStyle();
uiStyleFontSet(&style->widget);
- return BLF_width(style->widget.uifont_id, str);
+ return BLF_width(style->widget.uifont_id, str, BLF_DRAW_STR_DUMMY_MAX);
}
float file_font_pointsize(void)
@@ -627,14 +627,14 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche
if (!match) {
BLI_strncpy(matched_file, file->relname, FILE_MAX);
}
- match = 1;
+ match++;
}
}
return match;
}
-bool autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
+int autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
{
SpaceFile *sfile = CTX_wm_space_file(C);
int match = AUTOCOMPLETE_NO_MATCH;
@@ -684,10 +684,10 @@ bool autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
}
}
- return match == AUTOCOMPLETE_FULL_MATCH;
+ return match;
}
-bool autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
+int autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
{
SpaceFile *sfile = CTX_wm_space_file(C);
int match = AUTOCOMPLETE_NO_MATCH;
@@ -700,13 +700,14 @@ bool autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
for (i = 0; i < nentries; ++i) {
struct direntry *file = filelist_file(sfile->files, i);
- if (file && S_ISREG(file->type)) {
+ if (file && (S_ISREG(file->type) || S_ISDIR(file->type))) {
autocomplete_do_name(autocpl, file->relname);
}
}
match = autocomplete_end(autocpl, str);
}
- return match != AUTOCOMPLETE_NO_MATCH;
+
+ return match;
}
void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile)
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 1a8565a58b1..62048752fa1 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -395,7 +395,6 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_delete);
WM_operatortype_append(FILE_OT_rename);
WM_operatortype_append(FILE_OT_smoothscroll);
- WM_operatortype_append(FILE_OT_directory);
}
/* NOTE: do not add .blend file reading on this level */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 295f8bd9ff2..a01f4bcaaf1 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -301,11 +301,11 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
{
uiItemL(col, IFACE_("Key:"), ICON_NONE);
- but = uiDefButR(block, NUM, B_REDR, IFACE_("Frame"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, IFACE_("Frame:"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "co", 0, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt);
- but = uiDefButR(block, NUM, B_REDR, IFACE_("Value"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, IFACE_("Value:"), 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "co", 1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt);
uiButSetUnitType(but, unit);
@@ -315,11 +315,11 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) {
uiItemL(col, IFACE_("Left Handle:"), ICON_NONE);
- but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
- but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
uiButSetUnitType(but, unit);
@@ -329,11 +329,11 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa)
if (bezt->ipo == BEZT_IPO_BEZ) {
uiItemL(col, IFACE_("Right Handle:"), ICON_NONE);
- but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
- but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ but = uiDefButR(block, NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y,
&bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt);
uiButSetUnitType(but, unit);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index db13e2a4024..a35395abaf2 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -872,11 +872,12 @@ void GRAPH_OT_duplicate(wmOperatorType *ot)
/* ******************** Delete Keyframes Operator ************************* */
-static void delete_graph_keys(bAnimContext *ac)
+static bool delete_graph_keys(bAnimContext *ac)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ bool changed = false;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
@@ -888,7 +889,7 @@ static void delete_graph_keys(bAnimContext *ac)
AnimData *adt = ale->adt;
/* delete selected keyframes only */
- delete_fcurve_keys(fcu);
+ changed |= delete_fcurve_keys(fcu);
/* Only delete curve too if it won't be doing anything anymore */
if ((fcu->totvert == 0) &&
@@ -901,20 +902,23 @@ static void delete_graph_keys(bAnimContext *ac)
/* free filtered list */
BLI_freelistN(&anim_data);
+
+ return changed;
}
/* ------------------- */
-static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
+static int graphkeys_delete_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ bool changed;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* delete keyframes */
- delete_graph_keys(&ac);
+ changed = delete_graph_keys(&ac);
/* validate keyframes after editing */
ANIM_editkeyframes_refresh(&ac);
@@ -922,6 +926,9 @@ static int graphkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ if (changed)
+ BKE_report(op->reports, RPT_INFO, "Deleted selected keyframes");
+
return OPERATOR_FINISHED;
}
@@ -933,7 +940,6 @@ void GRAPH_OT_delete(wmOperatorType *ot)
ot->description = "Remove all selected keyframes";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = graphkeys_delete_exec;
ot->poll = graphop_editable_keyframes_poll;
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 50d8051a73e..62ac3c2d985 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
+ ../../gpu
)
set(INC_SYS
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index 89def32e70f..d878a726b55 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -42,6 +42,7 @@ incs = [
'../../makesrna',
'../../render/extern/include',
'../../windowmanager',
+ '../../gpu',
]
incs = ' '.join(incs)
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 89e57955339..3d5f6a6ce7e 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -195,21 +195,21 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_Y, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
if (zp) {
glColor3ub(255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (zpf) {
glColor3ub(255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (channels >= 3) {
@@ -222,7 +222,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), " R:-");
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
glColor3ubv(green);
if (fp)
@@ -233,7 +233,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), " G:-");
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
glColor3ubv(blue);
if (fp)
@@ -244,7 +244,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), " B:-");
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
if (channels == 4) {
glColor3ub(255, 255, 255);
@@ -256,7 +256,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), "- ");
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (color_manage) {
@@ -276,7 +276,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
}
@@ -350,12 +350,12 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), "V:%-.4f", val);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
else if (channels >= 3) {
rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
@@ -364,22 +364,22 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), "H:%-.4f", hue);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
BLI_snprintf(str, sizeof(str), " S:%-.4f", sat);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
BLI_snprintf(str, sizeof(str), " V:%-.4f", val);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str);
+ dx += BLF_width(blf_mono_font, str, sizeof(str));
}
(void)dx;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index b7d3407b826..2ea77bba681 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -58,6 +58,8 @@
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "GPU_draw.h"
+
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -85,6 +87,7 @@
#include "PIL_time.h"
#include "image_intern.h"
+#include "ED_sculpt.h"
/******************** view navigation utilities *********************/
@@ -1792,6 +1795,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
else {
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
if (tex && tex->type == TEX_IMAGE) {
+ if (tex->ima)
+ id_us_min(&tex->ima->id);
tex->ima = ima;
ED_area_tag_redraw(CTX_wm_area(C));
}
@@ -1858,6 +1863,9 @@ static int image_invert_exec(bContext *C, wmOperator *op)
{
Image *ima = CTX_data_edit_image(C);
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ /* undo is supported only on image paint mode currently */
+ bool support_undo = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
/* flags indicate if this channel should be inverted */
const short r = RNA_boolean_get(op->ptr, "invert_r");
@@ -1870,6 +1878,14 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (ibuf == NULL) /* TODO: this should actually never happen, but does for render-results -> cleanup */
return OPERATOR_CANCELLED;
+ if (support_undo) {
+ ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ ED_image_undo_restore, ED_image_undo_free);
+ /* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
+ * but better do this right in case someone copies this for a tool that uses partial redraw better */
+ ED_imapaint_clear_partial_redraw();
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ }
/* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
if (ibuf->rect_float) {
@@ -1901,9 +1917,16 @@ static int image_invert_exec(bContext *C, wmOperator *op)
}
ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+
if (ibuf->mipmap[0])
ibuf->userflags |= IB_MIPMAP_INVALID;
+ if (support_undo)
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+
+ /* force GPU reupload, all image is invalid */
+ GPU_free_image(ima);
+
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
BKE_image_release_ibuf(ima, ibuf, NULL);
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index b096b8f3e2b..827e4427ca0 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -223,7 +223,7 @@ static int borderselect_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
ReportList *reports = CTX_wm_reports(C);
int report_mask = info_report_mask(sinfo);
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
Report *report_min, *report_max, *report;
//View2D *v2d = UI_view2d_fromcontext(C);
@@ -231,7 +231,7 @@ static int borderselect_exec(bContext *C, wmOperator *op)
rcti rect;
//rctf rectf, rq;
- short selecting = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
+ const bool select = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
//int mval[2];
WM_operator_properties_border_to_rcti(op, &rect);
@@ -287,7 +287,7 @@ static int borderselect_exec(bContext *C, wmOperator *op)
if ((report->type & report_mask) == 0)
continue;
- if (selecting)
+ if (select)
report->flag |= SELECT;
else
report->flag &= ~SELECT;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 9686c6dfc29..4babda08898 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -296,7 +296,16 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
/* Dupli Verts/Faces */
- int tot = count_duplilist(ob->parent);
+ int tot;
+
+ /* metaball dupli-instances are tessellated once */
+ if (ob->type == OB_MBALL) {
+ tot = 1;
+ }
+ else {
+ tot = count_duplilist(ob->parent);
+ }
+
stats->totobj += tot;
stats_object(ob, base->flag & SELECT, tot, stats);
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index aaa52597357..96e0de17918 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -220,6 +220,9 @@ static void info_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "INFO_OT_report_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_report_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "INFO_OT_report_copy", CKEY, KM_PRESS, KM_CTRL, 0);
+#ifdef __APPLE__
+ WM_keymap_add_item(keymap, "INFO_OT_report_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
+#endif
}
/* add handlers, stuff you only do once or on area/region changes */
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 30c7b5de2f1..6b0460ce5cd 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -32,7 +32,6 @@ set(INC
../../windowmanager
../../compositor
../../../../intern/guardedalloc
- ../../../../intern/opennl/extern
)
set(INC_SYS
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 50a4b515490..da599f8608d 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -406,7 +406,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
/* title color */
UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.8f, 10);
- width = BLF_width(fontid, label);
+ width = BLF_width(fontid, label, sizeof(label));
ascender = BLF_ascender(fontid);
/* 'x' doesn't need aspect correction */
@@ -753,6 +753,11 @@ static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA
}
}
+static void node_shader_buts_lamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "lamp_object", 0, IFACE_("Lamp Object"), ICON_NONE);
+}
+
static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE);
@@ -1002,6 +1007,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_GEOMETRY:
ntype->draw_buttons = node_shader_buts_geometry;
break;
+ case SH_NODE_LAMP:
+ ntype->draw_buttons = node_shader_buts_lamp;
+ break;
case SH_NODE_ATTRIBUTE:
ntype->draw_buttons = node_shader_buts_attribute;
break;
@@ -1635,7 +1643,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
else {
col = uiLayoutColumn(layout, TRUE);
- uiItemL(col, IFACE_("File Path:"), ICON_NONE);
+ uiItemL(col, IFACE_("File Subpath:"), ICON_NONE);
row = uiLayoutRow(col, FALSE);
uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
@@ -2002,7 +2010,7 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN
const float backdropWidth = backdrop->x;
const float backdropHeight = backdrop->y;
const float aspect = backdropWidth / backdropHeight;
- const float rad = DEG2RADF(-boxmask->rotation);
+ const float rad = -boxmask->rotation;
const float cosine = cosf(rad);
const float sine = sinf(rad);
const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
@@ -2040,7 +2048,7 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop
const float backdropWidth = backdrop->x;
const float backdropHeight = backdrop->y;
const float aspect = backdropWidth / backdropHeight;
- const float rad = DEG2RADF(-ellipsemask->rotation);
+ const float rad = -ellipsemask->rotation;
const float cosine = cosf(rad);
const float sine = sinf(rad);
const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
@@ -3115,7 +3123,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
toreroute = 0;
}
- dist = UI_GetThemeValue(TH_NODE_CURVING) * 0.10f * ABS(vec[0][0] - vec[3][0]);
+ dist = UI_GetThemeValue(TH_NODE_CURVING) * 0.10f * fabsf(vec[0][0] - vec[3][0]);
deltax = vec[3][0] - vec[0][0];
deltay = vec[3][1] - vec[0][1];
/* check direction later, for top sockets */
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 00769975893..4b1a06fa923 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -90,9 +90,6 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
ntreeUpdateTree(bmain, snode->edittree);
ED_node_set_active(bmain, snode->edittree, node);
- if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
- node->flag &= ~NODE_PREVIEW;
-
snode_update(snode, node);
if (snode->nodetree->type == NTREE_TEXTURE) {
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 6f2f8dee105..5ca853e6020 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -562,16 +562,21 @@ int node_tweak_area_default(bNode *node, int x, int y)
int node_get_colorid(bNode *node)
{
switch (node->typeinfo->nclass) {
- case NODE_CLASS_INPUT: return TH_NODE_IN_OUT;
- case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_IN_OUT : TH_NODE;
+ case NODE_CLASS_INPUT: return TH_NODE_INPUT;
+ case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_OUTPUT : TH_NODE;
case NODE_CLASS_CONVERTOR: return TH_NODE_CONVERTOR;
- case NODE_CLASS_OP_COLOR:
- case NODE_CLASS_OP_VECTOR:
- case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR;
+ case NODE_CLASS_OP_COLOR: return TH_NODE_COLOR;
+ case NODE_CLASS_OP_VECTOR: return TH_NODE_VECTOR;
+ case NODE_CLASS_OP_FILTER: return TH_NODE_FILTER;
case NODE_CLASS_GROUP: return TH_NODE_GROUP;
case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
case NODE_CLASS_MATTE: return TH_NODE_MATTE;
case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
+ case NODE_CLASS_TEXTURE: return TH_NODE_TEXTURE;
+ case NODE_CLASS_SHADER: return TH_NODE_SHADER;
+ case NODE_CLASS_SCRIPT: return TH_NODE_SCRIPT;
+ case NODE_CLASS_PATTERN: return TH_NODE_PATTERN;
+ case NODE_CLASS_LAYOUT: return TH_NODE_LAYOUT;
default: return TH_NODE;
}
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 2e3e747618b..64326bd7993 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -448,7 +448,7 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
rcti rect;
rctf rectf;
int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
WM_operator_properties_border_to_rcti(op, &rect);
@@ -573,7 +573,7 @@ void NODE_OT_select_circle(wmOperatorType *ot)
/* ****** Lasso Select ****** */
-static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves, short select)
+static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, short select)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
@@ -581,7 +581,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
ARegion *ar = CTX_wm_region(C);
rcti rect;
- int change = FALSE;
+ bool changed = false;
/* get rectangle from operator */
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -601,15 +601,15 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
nodeSetSelected(node, select);
- change = TRUE;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
- return change;
+ return changed;
}
static int node_lasso_select_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index a67a8791a64..b544e753965 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -436,6 +436,7 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
char name[UI_MAX_NAME_STR];
const char *cur_node_name = NULL;
int i, num = 0;
+ int icon = ICON_NONE;
if (compatibility && !(ntype->compatibility & compatibility))
continue;
@@ -461,7 +462,6 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
uiItemL(column, IFACE_(cname), ICON_NODE);
but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
first = 0;
}
@@ -469,18 +469,21 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
if (num > 1) {
if (!cur_node_name || !STREQ(cur_node_name, items[i].node_name)) {
cur_node_name = items[i].node_name;
- uiItemL(column, IFACE_(cur_node_name), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
+ /* XXX Do not use uiItemL here, it would add an empty icon as we are in a menu! */
+ uiDefBut(block, LABEL, 0, IFACE_(cur_node_name), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, "");
}
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(items[i].socket_name));
+
+ BLI_snprintf(name, UI_MAX_NAME_STR, "%s", IFACE_(items[i].socket_name));
+ icon = ICON_BLANK1;
}
- else
+ else {
BLI_strncpy(name, IFACE_(items[i].node_name), UI_MAX_NAME_STR);
+ icon = ICON_NONE;
+ }
- but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
+ but = uiDefIconTextBut(block, BUT, 0, icon, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
argN = MEM_dupallocN(arg);
argN->item = items[i];
@@ -528,7 +531,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
if (sock->link) {
uiItemL(column, IFACE_("Link"), ICON_NONE);
but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
+ but->drawflag = UI_BUT_TEXT_LEFT;
but = uiDefBut(block, BUT, 0, IFACE_("Remove"), 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Remove nodes connected to the input"));
@@ -564,7 +567,8 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
but = uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
but->type = MENU;
- but->flag |= UI_TEXT_LEFT | UI_BUT_NODE_LINK;
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ but->flag |= UI_BUT_NODE_LINK;
but->poin = (char *)but;
but->func_argN = arg;
@@ -654,7 +658,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
uiItemL(row, label, ICON_NONE);
bt = block->buttons.last;
- bt->flag = UI_TEXT_LEFT;
+ bt->drawflag = UI_BUT_TEXT_LEFT;
if (dependency_loop) {
row = uiLayoutRow(split, FALSE);
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 6ae8a1f94b1..2fe63c4b895 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -555,11 +555,15 @@ static SpaceLink *node_duplicate(SpaceLink *sl)
SpaceNode *snode = (SpaceNode *)sl;
SpaceNode *snoden = MEM_dupallocN(snode);
+ BLI_duplicatelist(&snoden->treepath, &snode->treepath);
+
/* clear or remove stuff from old */
- snoden->nodetree = NULL;
snoden->linkdrag.first = snoden->linkdrag.last = NULL;
-
- BLI_duplicatelist(&snoden->treepath, &snode->treepath);
+
+ /* Note: no need to set node tree user counts,
+ * the editor only keeps at least 1 (id_us_ensure_real),
+ * which is already done by the original SpaceNode.
+ */
return (SpaceLink *)snoden;
}
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 26fe2edd0d1..4db47b75502 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -28,7 +28,6 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
- ../../../../intern/opennl/extern
)
set(INC_SYS
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 559fb6f932e..3f0ad45de56 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -273,18 +273,18 @@ static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), const wmEve
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- bool change = false;
+ bool changed = false;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1);
for (te = soops->tree.first; te; te = te->next) {
if (do_outliner_item_rename(C, ar, soops, te, fmval)) {
- change = true;
+ changed = true;
break;
}
}
- return change ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
+ return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index d1d512409ee..b10b8a46ec6 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -78,7 +78,7 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se
{
TreeElement *te;
TreeStoreElem *tselem;
- int change = 0;
+ bool changed = false;
for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) {
tselem = TREESTORE(te);
@@ -101,7 +101,7 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se
else
tselem->flag &= ~TSE_SELECTED;
- change |= 1;
+ changed |= true;
}
}
else if (TSELEM_OPEN(tselem, soops)) {
@@ -113,12 +113,12 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se
* function correctly
*/
(*index)--;
- change |= outliner_select(soops, &te->subtree, index, selecting);
+ changed |= outliner_select(soops, &te->subtree, index, selecting);
(*index)++;
}
}
- return change;
+ return changed;
}
/* ****************************************************** */
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 63aa92517a7..2952bdb042c 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -826,8 +826,8 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
* may generate strips with the same name (which will mess up animdata)
*/
-static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
- Sequence * (*cut_seq)(Scene *, Sequence *, int))
+static bool cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
+ Sequence * (*cut_seq)(Scene *, Sequence *, int))
{
Sequence *seq, *seq_next_iter;
Sequence *seq_first_new = NULL;
@@ -1569,7 +1569,7 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
int cut_side, cut_hard, cut_frame;
- int changed;
+ bool changed;
cut_frame = RNA_int_get(op->ptr, "frame");
cut_hard = RNA_enum_get(op->ptr, "type");
@@ -1601,6 +1601,15 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
}
SEQ_END;
}
+
+ SEQP_BEGIN (ed, seq)
+ {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(scene, seq);
+ }
+ }
+ SEQ_END;
+
/* as last: */
BKE_sequencer_sort(scene);
}
@@ -2075,7 +2084,6 @@ void SEQUENCER_OT_meta_make(wmOperatorType *ot)
ot->description = "Group selected strips into a metastrip";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = sequencer_meta_make_exec;
ot->poll = sequencer_edit_poll;
@@ -2146,7 +2154,6 @@ void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
ot->description = "Put the contents of a metastrip back in the sequencer";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = sequencer_meta_separate_exec;
ot->poll = sequencer_edit_poll;
@@ -2479,20 +2486,20 @@ static int find_next_prev_edit(Scene *scene, int cfra,
return cfra;
}
-static int strip_jump_internal(Scene *scene,
- const short side,
- const short do_skip_mute, const short do_center)
+static bool strip_jump_internal(Scene *scene,
+ const short side,
+ const short do_skip_mute, const short do_center)
{
- int change = FALSE;
+ bool changed = false;
int cfra = CFRA;
int nfra = find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center);
if (nfra != cfra) {
CFRA = nfra;
- change = TRUE;
+ changed = true;
}
- return change;
+ return changed;
}
static int sequencer_strip_jump_poll(bContext *C)
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 45f05d56076..d1cc2091265 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -188,7 +188,7 @@ static void select_neighbor_from_last(Scene *scene, int lr)
{
Sequence *seq = BKE_sequencer_active_get(scene);
Sequence *neighbor;
- int change = 0;
+ bool changed = false;
if (seq) {
neighbor = find_neighboring_sequence(scene, seq, lr, -1);
if (neighbor) {
@@ -207,10 +207,10 @@ static void select_neighbor_from_last(Scene *scene, int lr)
break;
}
seq->flag |= SELECT;
- change = 1;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
}
}
#endif
@@ -553,14 +553,15 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
/* run recursively to select linked */
-static int select_more_less_seq__internal(Scene *scene, int sel, int linked)
+static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked)
{
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq, *neighbor;
- int change = 0;
+ bool changed = false;
int isel;
- if (ed == NULL) return 0;
+ if (ed == NULL)
+ return changed;
if (sel) {
sel = SELECT;
@@ -587,20 +588,20 @@ static int select_more_less_seq__internal(Scene *scene, int sel, int linked)
if (sel) { neighbor->flag |= SELECT; recurs_sel_seq(neighbor); }
else neighbor->flag &= ~SELECT;
if (linked == 0) neighbor->tmp = (Sequence *)1;
- change = 1;
+ changed = true;
}
neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
if (neighbor) {
if (sel) { neighbor->flag |= SELECT; recurs_sel_seq(neighbor); }
else neighbor->flag &= ~SELECT;
if (linked == 0) neighbor->tmp = (void *)1;
- change = 1;
+ changed = true;
}
}
}
}
- return change;
+ return changed;
}
@@ -850,8 +851,8 @@ static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
Sequence *seq;
rcti rect;
rctf rectf, rq;
- short selecting = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
- int extend = RNA_boolean_get(op->ptr, "extend");
+ const bool select = (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
int mval[2];
if (ed == NULL)
@@ -870,7 +871,7 @@ static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
seq_rectf(seq, &rq);
if (BLI_rctf_isect(&rq, &rectf, NULL)) {
- if (selecting) seq->flag |= SELECT;
+ if (select) seq->flag |= SELECT;
else seq->flag &= ~SEQ_ALLSEL;
recurs_sel_seq(seq);
}
@@ -930,16 +931,16 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
#define SEQ_USE_DATA(_seq) (ELEM3(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
-static short select_grouped_type(Editing *ed, Sequence *actseq)
+static bool select_grouped_type(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
SEQP_BEGIN (ed, seq)
{
if (seq->type == actseq->type) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -947,17 +948,17 @@ static short select_grouped_type(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_type_basic(Editing *ed, Sequence *actseq)
+static bool select_grouped_type_basic(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
short is_sound = SEQ_IS_SOUND(actseq);
SEQP_BEGIN (ed, seq)
{
if (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq)) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -965,17 +966,17 @@ static short select_grouped_type_basic(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_type_effect(Editing *ed, Sequence *actseq)
+static bool select_grouped_type_effect(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
short is_effect = SEQ_IS_EFFECT(actseq);
SEQP_BEGIN (ed, seq)
{
if (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq)) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -983,10 +984,10 @@ static short select_grouped_type_effect(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_data(Editing *ed, Sequence *actseq)
+static bool select_grouped_data(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
char *dir = actseq->strip ? actseq->strip->dir : NULL;
if (!SEQ_USE_DATA(actseq))
@@ -997,7 +998,7 @@ static short select_grouped_data(Editing *ed, Sequence *actseq)
{
if (SEQ_HAS_PATH(seq) && seq->strip && strcmp(seq->strip->dir, dir) == 0) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1008,7 +1009,7 @@ static short select_grouped_data(Editing *ed, Sequence *actseq)
{
if (seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1019,7 +1020,7 @@ static short select_grouped_data(Editing *ed, Sequence *actseq)
{
if (seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1030,7 +1031,7 @@ static short select_grouped_data(Editing *ed, Sequence *actseq)
{
if (seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1039,10 +1040,10 @@ static short select_grouped_data(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_effect(Editing *ed, Sequence *actseq)
+static bool select_grouped_effect(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
short effects[SEQ_TYPE_EFFECT_MAX + 1];
int i;
@@ -1063,7 +1064,7 @@ static short select_grouped_effect(Editing *ed, Sequence *actseq)
if (seq->seq1) seq->seq1->flag |= SELECT;
if (seq->seq2) seq->seq2->flag |= SELECT;
if (seq->seq3) seq->seq3->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1071,16 +1072,16 @@ static short select_grouped_effect(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_time_overlap(Editing *ed, Sequence *actseq)
+static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
{
Sequence *seq;
- short changed = FALSE;
+ bool changed = false;
SEQP_BEGIN (ed, seq)
{
if (!((seq->startdisp >= actseq->enddisp) || (seq->enddisp < actseq->startdisp))) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
SEQ_END;
@@ -1088,10 +1089,10 @@ static short select_grouped_time_overlap(Editing *ed, Sequence *actseq)
return changed;
}
-static short select_grouped_effect_link(Editing *ed, Sequence *actseq)
+static bool select_grouped_effect_link(Editing *ed, Sequence *actseq)
{
Sequence *seq = NULL;
- short changed = FALSE;
+ bool changed = false;
short is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
int startdisp = actseq->startdisp;
int enddisp = actseq->enddisp;
@@ -1131,7 +1132,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq)
seq->tmp = SET_INT_IN_POINTER(TRUE);
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
/* Unfortunately, we must restart checks from the beginning. */
BKE_sequence_iterator_end(&iter);
@@ -1141,7 +1142,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq)
/* Video strips bellow active one, or any strip for audio (order do no matters here!). */
else if (seq->machine < machine || is_audio) {
seq->flag |= SELECT;
- changed = TRUE;
+ changed = true;
}
}
BKE_sequence_iterator_end(&iter);
@@ -1159,7 +1160,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, 0);
Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
int type = RNA_enum_get(op->ptr, "type");
- short changed = 0, extend;
+ bool changed = false, extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -1172,7 +1173,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
SEQP_BEGIN (ed, seq)
{
seq->flag &= ~SELECT;
- changed = TRUE;
+ changed = true;
}
SEQ_END;
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 4a4754e8adc..ae34754b108 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -234,28 +234,28 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
ARegion *ar_main = sequencer_find_region(sa, RGN_TYPE_WINDOW);
ARegion *ar_preview = sequencer_find_region(sa, RGN_TYPE_PREVIEW);
- int view_changed = 0;
+ bool view_changed = false;
switch (sseq->view) {
case SEQ_VIEW_SEQUENCE:
if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
ar_main->flag &= ~RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
ar_preview->flag |= RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
- view_changed = 1;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = 1;
+ view_changed = true;
}
break;
case SEQ_VIEW_PREVIEW:
@@ -263,42 +263,42 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
ar_main->flag |= RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
ar_preview->flag &= ~RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = 1;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = 1;
+ view_changed = true;
}
break;
case SEQ_VIEW_SEQUENCE_PREVIEW:
if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
ar_main->flag &= ~RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
ar_preview->flag &= ~RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = 1;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = 1;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_TOP) {
ar_preview->alignment = RGN_ALIGN_TOP;
- view_changed = 1;
+ view_changed = true;
}
break;
}
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index ee64d680319..37f7cf13928 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -534,7 +534,7 @@ static void text_properties_area_draw(const bContext *C, ARegion *ar)
/* this flag trick is make sure buttons have been added already */
if (st->flags & ST_FIND_ACTIVATE) {
- if (UI_textbutton_activate_event(C, ar, st, "find_text")) {
+ if (UI_textbutton_activate_rna(C, ar, st, "find_text")) {
/* if the panel was already open we need to do another redraw */
ScrArea *sa = CTX_wm_area(C);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_TEXT, sa);
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 7d5cff6a2d0..51477ec2ae7 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -46,9 +46,11 @@ set(SRC
drawvolume.c
space_view3d.c
view3d_buttons.c
+ view3d_camera_control.c
view3d_draw.c
view3d_edit.c
view3d_fly.c
+ view3d_walk.c
view3d_header.c
view3d_iterators.c
view3d_ops.c
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index de6fafb2cd8..8aced487160 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1878,7 +1878,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
/* if solid && posemode, we draw again with polygonoffset */
else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
}
else {
/* and we use selection indices if not done yet */
@@ -1986,7 +1986,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
/* restore things */
if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt > OB_WIRE) && (arm->flag & ARM_POSEMODE))
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
/* restore */
@@ -2154,7 +2154,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
index = 0;
}
else if (dt > OB_WIRE)
- bglPolygonOffset(rv3d->dist, 1.0f);
+ ED_view3d_polygon_offset(rv3d, 1.0);
else if (arm->flag & ARM_EDITMODE)
index = 0; /* do selection codes */
@@ -2221,7 +2221,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* pass */
}
else if (dt > OB_WIRE) {
- bglPolygonOffset(rv3d->dist, 0.0f);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
/* finally names and axes */
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index a08a6cc1478..52897aa023e 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -170,7 +170,7 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
/* Draw (Hidden) Edges */
setlinestyle(1);
@@ -188,7 +188,7 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
glDisable(GL_BLEND);
}
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
/* Draw Stippled Outline for selected faces */
glColor3ub(255, 255, 255);
@@ -196,7 +196,7 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
setlinestyle(0);
- bglPolygonOffset(rv3d->dist, 0.0); /* resets correctly now, even after calling accumulated offsets */
+ ED_view3d_polygon_offset(rv3d, 0.0); /* resets correctly now, even after calling accumulated offsets */
MEM_freeN(data.edge_flags);
}
@@ -1055,7 +1055,7 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm, const boo
* rather than the shading, this is also forced in wire view */
if (use_depth) {
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
}
else {
@@ -1070,7 +1070,7 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm, const boo
dm->drawMappedEdges(dm, (DMSetDrawOptions)edgemask_cb, user_data);
if (use_depth) {
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
glDepthMask(1);
}
else {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 2083da2d64f..225c58207e7 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1210,18 +1210,16 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
/* skip drawing extra info */
}
else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
- lvec[0] = lvec[1] = 0.0;
- lvec[2] = 1.0;
- x = rv3d->persmat[0][2];
- y = rv3d->persmat[1][2];
- z = rv3d->persmat[2][2];
- vvec[0] = x * ob->obmat[0][0] + y * ob->obmat[0][1] + z * ob->obmat[0][2];
- vvec[1] = x * ob->obmat[1][0] + y * ob->obmat[1][1] + z * ob->obmat[1][2];
- vvec[2] = x * ob->obmat[2][0] + y * ob->obmat[2][1] + z * ob->obmat[2][2];
-
- y = cosf(la->spotsize * (float)(M_PI / 360.0));
- spotvolume(lvec, vvec, y);
+
+ copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
+ copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
+ mul_mat3_m4_v3(ob->obmat, vvec);
+
x = -la->dist;
+ y = cosf(la->spotsize * 0.5f);
+ z = x * sqrtf(1.0f - y * y);
+
+ spotvolume(lvec, vvec, y);
mul_v3_fl(lvec, x);
mul_v3_fl(vvec, x);
@@ -1232,7 +1230,6 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
glVertex3fv(lvec);
glEnd();
- z = x * sqrtf(1.0f - y * y);
x *= y;
/* draw the circle/square at the end of the cone */
@@ -3126,7 +3123,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
if (dt > OB_WIRE) {
draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh);
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0);
}
else {
@@ -3176,7 +3173,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
* write to show selected edge wires better */
UI_ThemeColor(TH_WIRE_EDIT);
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0);
}
else {
@@ -3322,12 +3319,12 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
if (dt > OB_WIRE) {
glDepthMask(1);
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
GPU_disable_material();
}
#if 0 /* currently not needed */
else if (use_occlude_wire) {
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
#endif
}
@@ -3568,7 +3565,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
* otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
*/
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
}
@@ -3576,7 +3573,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
glDepthMask(1);
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
}
@@ -3586,10 +3583,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
if (!use_depth) glDisable(GL_DEPTH_TEST);
- else bglPolygonOffset(rv3d->dist, 1.0);
+ else ED_view3d_polygon_offset(rv3d, 1.0);
drawSelectedVertices(dm, ob->data);
if (!use_depth) glEnable(GL_DEPTH_TEST);
- else bglPolygonOffset(rv3d->dist, 0.0);
+ else ED_view3d_polygon_offset(rv3d, 0.0);
glPointSize(1.0f);
}
@@ -4058,7 +4055,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (BKE_mball_is_basis(ob)) {
lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
- if (ELEM(lb, lb->first, NULL)) {
+ if (ELEM(NULL, lb, lb->first)) {
BKE_displist_make_mball(scene, ob);
lb = &ob->curve_cache->disp;
}
@@ -5759,7 +5756,7 @@ static void draw_empty_cone(float size)
static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2])
{
cpack(0);
- bglPolygonOffset(rv3d->dist, -1.0);
+ ED_view3d_polygon_offset(rv3d, -1.0);
set_inverted_drawing(1);
glBegin(GL_QUADS);
glVertex2fv(textcurs[0]);
@@ -5768,7 +5765,7 @@ static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2])
glVertex2fv(textcurs[3]);
glEnd();
set_inverted_drawing(0);
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
@@ -6380,7 +6377,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
glColor3ubv(ob_wire_col);
}
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
@@ -6406,7 +6403,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
}
glDepthMask(1);
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
}
}
@@ -7559,7 +7556,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
else
bm_solidoffs = 1;
- bglPolygonOffset(rv3d->dist, 1.0);
+ ED_view3d_polygon_offset(rv3d, 1.0);
/* we draw edges always, for loop (select) tools */
bbs_mesh_wire(em, dm, bm_solidoffs);
@@ -7574,7 +7571,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
bm_vertoffs = bm_wireoffs;
}
- bglPolygonOffset(rv3d->dist, 0.0);
+ ED_view3d_polygon_offset(rv3d, 0.0);
dm->release(dm);
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index b803a4a8473..3f7d599f5d5 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -46,6 +46,7 @@
#include "BKE_icons.h"
#include "BKE_main.h"
#include "BKE_object.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "ED_render.h"
@@ -260,6 +261,19 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
}
#endif
+static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->render_engine) {
+ WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+ if (rv3d->render_engine->re)
+ RE_Database_Free(rv3d->render_engine->re);
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
+}
+
void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
{
wmWindowManager *wm = bmain->wm.first;
@@ -268,15 +282,8 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d && rv3d->render_engine) {
- WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
- if (rv3d->render_engine->re)
- RE_Database_Free(rv3d->render_engine->re);
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
+ if (ar->regiondata)
+ view3d_stop_render_preview(wm, ar);
}
}
}
@@ -507,14 +514,11 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
}
-static void view3d_main_area_exit(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
- if (rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
+ view3d_stop_render_preview(wm, ar);
if (rv3d->gpuoffscreen) {
GPU_offscreen_free(rv3d->gpuoffscreen);
@@ -770,6 +774,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_OB_VISIBLE:
case ND_LAYER:
case ND_RENDER_OPTIONS:
+ case ND_MARKERS:
case ND_MODE:
ED_region_tag_redraw(ar);
break;
@@ -827,7 +832,9 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_SHADING:
case ND_NODES:
if ((v3d->drawtype == OB_MATERIAL) ||
- (v3d->drawtype == OB_TEXTURE && scene->gm.matmode == GAME_MAT_GLSL))
+ (v3d->drawtype == OB_TEXTURE &&
+ (scene->gm.matmode == GAME_MAT_GLSL ||
+ BKE_scene_use_new_shading_nodes(scene))))
{
ED_region_tag_redraw(ar);
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index c4fdacaa915..3b4405a2c1c 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -422,11 +422,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
/* Curve... */
else if (totcurvedata == 1) {
- uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
- uiDefButR(block, NUM, 0, IFACE_("Radius"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Radius:"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL);
- uiDefButR(block, NUM, 0, IFACE_("Tilt"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Tilt:"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "tilt", 0, -tilt_limit, tilt_limit, 1, 3, NULL);
}
else if (totcurvedata > 1) {
@@ -444,7 +444,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
/* Lattice... */
else if (totlattdata == 1) {
- uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
}
else if (totlattdata > 1) {
@@ -859,7 +859,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
but_ptr = uiButGetOperatorPtrRNA(but);
RNA_int_set(but_ptr, "weight_group", i);
- uiButSetFlag(but, UI_TEXT_RIGHT);
+ uiButSetDrawFlag(but, UI_BUT_TEXT_RIGHT);
if (ob->actdef != i + 1) {
uiButSetFlag(but, UI_BUT_INACTIVE);
}
@@ -873,7 +873,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "",
xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y,
&dw->weight, 0.0, 1.0, 1, 3, "");
- uiButSetFlag(but, UI_TEXT_LEFT);
+ uiButSetDrawFlag(but, UI_BUT_TEXT_LEFT);
if (locked) {
lock_count++;
}
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
new file mode 100644
index 00000000000..2797125485c
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -0,0 +1,364 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_camera_control.c
+ * \ingroup spview3d
+ *
+ * The purpose of View3DCameraControl is to allow editing \a rv3d manipulation
+ * (mainly \a ofs and \a viewquat) for the purpose of view navigation
+ * without having to worry about positioning the camera, its parent...
+ * or other details.
+ *
+ *
+ * Typical view-control usage:
+ *
+ * - aquire a view-control (#ED_view3d_control_aquire).
+ * - modify ``rv3d->ofs``, ``rv3d->viewquat``.
+ * - update the view data (#ED_view3d_control_aquire) - within a loop which draws the viewport.
+ * - finish and release the view-control (#ED_view3d_control_release),
+ * either keeping the current view or restoring the initial view.
+ *
+ * Notes:
+ *
+ * - when acquiring ``rv3d->dist`` is set to zero
+ * (so ``rv3d->ofs`` is always the view-point)
+ * - updating can optionally keyframe the camera object.
+ */
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+
+#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 */
+
+#include "BLI_strict_flags.h"
+
+
+typedef struct View3DCameraControl {
+
+ /* -------------------------------------------------------------------- */
+ /* Context (assign these to vars before use) */
+ Scene *ctx_scene;
+ View3D *ctx_v3d;
+ RegionView3D *ctx_rv3d;
+
+
+ /* -------------------------------------------------------------------- */
+ /* internal vars */
+
+ /* for parenting calculation */
+ float view_mat_prev[4][4];
+
+
+ /* -------------------------------------------------------------------- */
+ /* optional capabilities */
+
+ bool use_parent_root;
+
+
+ /* -------------------------------------------------------------------- */
+ /* intial values */
+
+ /* root most parent */
+ Object *root_parent;
+
+ /* backup values */
+ float dist_backup; /* backup the views distance since we use a zero dist for fly mode */
+ float ofs_backup[3]; /* backup the views offset in case the user cancels flying in non camera mode */
+
+ /* backup the views quat in case the user cancels flying in non camera mode.
+ * (quat for view, eul for camera) */
+ float rot_backup[4];
+ char persp_backup; /* remember if were ortho or not, only used for restoring the view if it was a ortho view */
+
+ /* are we flying an ortho camera in perspective view,
+ * which was originally in ortho view?
+ * could probably figure it out but better be explicit */
+ bool is_ortho_cam;
+
+ void *obtfm; /* backup the objects transform */
+} View3DCameraControl;
+
+
+BLI_INLINE Object *view3d_cameracontrol_object(View3DCameraControl *vctrl)
+{
+ return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera;
+}
+
+
+/**
+ * Returns the object which is being manipulated or NULL.
+ */
+Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
+{
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ return view3d_cameracontrol_object(vctrl);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/**
+ * Creates a #View3DControl handle and sets up
+ * the view for first-person style navigation.
+ */
+struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
+ Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const bool use_parent_root)
+{
+ View3DCameraControl *vctrl;
+
+ vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
+
+ /* Store context */
+ vctrl->ctx_scene = scene;
+ vctrl->ctx_v3d = v3d;
+ vctrl->ctx_rv3d = rv3d;
+
+ vctrl->use_parent_root = use_parent_root;
+
+ vctrl->persp_backup = rv3d->persp;
+ vctrl->dist_backup = rv3d->dist;
+
+ /* check for flying ortho camera - which we cant support well
+ * we _could_ also check for an ortho camera but this is easier */
+ if ((rv3d->persp == RV3D_CAMOB) &&
+ (rv3d->is_persp == false))
+ {
+ ((Camera *)v3d->camera->data)->type = CAM_PERSP;
+ vctrl->is_ortho_cam = true;
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *ob_back;
+ if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) {
+ while (vctrl->root_parent->parent)
+ vctrl->root_parent = vctrl->root_parent->parent;
+ ob_back = vctrl->root_parent;
+ }
+ else {
+ ob_back = v3d->camera;
+ }
+
+ /* store the original camera loc and rot */
+ vctrl->obtfm = BKE_object_tfm_backup(ob_back);
+
+ BKE_object_where_is_calc(scene, v3d->camera);
+ negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
+
+ rv3d->dist = 0.0;
+ }
+ else {
+ float tvec[3];
+ /* perspective or ortho */
+ if (rv3d->persp == RV3D_ORTHO)
+ rv3d->persp = RV3D_PERSP; /* if ortho projection, make perspective */
+
+ copy_qt_qt(vctrl->rot_backup, rv3d->viewquat);
+ copy_v3_v3(vctrl->ofs_backup, rv3d->ofs);
+
+ /* the dist defines a vector that is infront of the offset
+ * to rotate the view about.
+ * this is no good for fly mode because we
+ * want to rotate about the viewers center.
+ * but to correct the dist removal we must
+ * alter offset so the view doesn't jump. */
+
+ rv3d->dist = 0.0f;
+
+ copy_v3_fl3(tvec, 0.0f, 0.0f, vctrl->dist_backup);
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+ sub_v3_v3(rv3d->ofs, tvec);
+ /* Done with correcting for the dist */
+ }
+
+ ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+
+ return vctrl;
+}
+
+
+/**
+ * Updates cameras from the ``rv3d`` values, optionally auto-keyframing.
+ */
+void ED_view3d_cameracontrol_update(
+ View3DCameraControl *vctrl,
+ /* args for keyframing */
+ const bool use_autokey,
+ struct bContext *C, const bool do_rotate, const bool do_translate)
+{
+ /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
+
+ Scene *scene = vctrl->ctx_scene;
+ View3D *v3d = vctrl->ctx_v3d;
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
+
+ ID *id_key;
+
+ /* transform the parent or the camera? */
+ if (vctrl->root_parent) {
+ Object *ob_update;
+
+ float view_mat[4][4];
+ float prev_view_imat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
+
+ invert_m4_m4(prev_view_imat, vctrl->view_mat_prev);
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
+ mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);
+
+ BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false);
+
+ ob_update = v3d->camera->parent;
+ while (ob_update) {
+ DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ ob_update = ob_update->parent;
+ }
+
+ copy_m4_m4(vctrl->view_mat_prev, view_mat);
+
+ id_key = &vctrl->root_parent->id;
+ }
+ else {
+ float view_mat[4][4];
+ float size_mat[4][4];
+ float size_back[3];
+
+ /* even though we handle the size matrix, this still changes over time */
+ copy_v3_v3(size_back, v3d->camera->size);
+
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ size_to_mat4(size_mat, v3d->camera->size);
+ mul_m4_m4m4(view_mat, view_mat, size_mat);
+
+ BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
+
+ copy_v3_v3(v3d->camera->size, size_back);
+
+ id_key = &v3d->camera->id;
+ }
+
+ /* record the motion */
+ if (use_autokey && autokeyframe_cfra_can_key(scene, id_key)) {
+ ListBase dsources = {NULL, NULL};
+
+ /* add data-source override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
+
+ /* insert keyframes
+ * 1) on the first frame
+ * 2) on each subsequent frame
+ * TODO: need to check in future that frame changed before doing this
+ */
+ if (do_rotate) {
+ struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ }
+ if (do_translate) {
+ struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
+ }
+}
+
+
+/**
+ * Release view control.
+ *
+ * \param restore Sets the view state to the values that were set
+ * before #ED_view3d_control_aquire was called.
+ */
+void ED_view3d_cameracontrol_release(
+ View3DCameraControl *vctrl,
+ const bool restore)
+{
+ View3D *v3d = vctrl->ctx_v3d;
+ RegionView3D *rv3d = vctrl->ctx_rv3d;
+
+ rv3d->dist = vctrl->dist_backup;
+ if (restore) {
+ /* Revert to original view? */
+ if (vctrl->persp_backup == RV3D_CAMOB) { /* a camera view */
+ Object *ob_back = view3d_cameracontrol_object(vctrl);
+
+ /* store the original camera loc and rot */
+ BKE_object_tfm_restore(ob_back, vctrl->obtfm);
+
+ DAG_id_tag_update(&ob_back->id, OB_RECALC_OB);
+ }
+ else {
+ /* Non Camera we need to reset the view back to the original location bacause the user canceled*/
+ copy_qt_qt(rv3d->viewquat, vctrl->rot_backup);
+ rv3d->persp = vctrl->persp_backup;
+ }
+ /* always, is set to zero otherwise */
+ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
+ }
+ else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */
+ DAG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB);
+
+ /* always, is set to zero otherwise */
+ copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
+ }
+ else { /* not camera */
+ float tvec[3];
+
+ /* Apply the fly mode view */
+ /* restore the dist */
+ copy_v3_fl3(tvec, 0.0f, 0.0f, vctrl->dist_backup);
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+ add_v3_v3(rv3d->ofs, tvec);
+ /* Done with correcting for the dist */
+ }
+
+ if (vctrl->is_ortho_cam) {
+ ((Camera *)v3d->camera->data)->type = CAM_ORTHO;
+ }
+
+ if (vctrl->obtfm) {
+ MEM_freeN(vctrl->obtfm);
+ }
+
+ MEM_freeN(vctrl);
+}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index dc00e55e0f4..9dd6ab8f841 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -583,7 +583,9 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
float ydisp = 0.0; /* vertical displacement to allow obj info text */
int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
float vec[3];
+ char axis_text[2] = "x";
float dx, dy;
+ int i;
startx += rect->xmin;
starty += rect->ymin;
@@ -594,60 +596,27 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- /* X */
- vec[0] = 1;
- vec[1] = vec[2] = 0;
- mul_qt_v3(rv3d->viewquat, vec);
- dx = vec[0] * k;
- dy = vec[1] * k;
-
- UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright);
- glBegin(GL_LINES);
- glVertex2f(startx, starty + ydisp);
- glVertex2f(startx + dx, starty + dy + ydisp);
- glEnd();
-
- if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "x", 1);
- }
-
- /* BLF_draw_default disables blending */
- glEnable(GL_BLEND);
-
- /* Y */
- vec[1] = 1;
- vec[0] = vec[2] = 0;
- mul_qt_v3(rv3d->viewquat, vec);
- dx = vec[0] * k;
- dy = vec[1] * k;
-
- UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright);
- glBegin(GL_LINES);
- glVertex2f(startx, starty + ydisp);
- glVertex2f(startx + dx, starty + dy + ydisp);
- glEnd();
+ for (i = 0; i < 3; i++) {
+ zero_v3(vec);
+ vec[i] = 1.0f;
+ mul_qt_v3(rv3d->viewquat, vec);
+ dx = vec[0] * k;
+ dy = vec[1] * k;
- if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "y", 1);
- }
+ UI_ThemeColorShadeAlpha(TH_AXIS_X + i, 0, bright);
+ glBegin(GL_LINES);
+ glVertex2f(startx, starty + ydisp);
+ glVertex2f(startx + dx, starty + dy + ydisp);
+ glEnd();
- glEnable(GL_BLEND);
-
- /* Z */
- vec[2] = 1;
- vec[1] = vec[0] = 0;
- mul_qt_v3(rv3d->viewquat, vec);
- dx = vec[0] * k;
- dy = vec[1] * k;
+ if (fabsf(dx) > toll || fabsf(dy) > toll) {
+ BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1);
+ }
- UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright);
- glBegin(GL_LINES);
- glVertex2f(startx, starty + ydisp);
- glVertex2f(startx + dx, starty + dy + ydisp);
- glEnd();
+ axis_text[0]++;
- if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "z", 1);
+ /* BLF_draw_default disables blending */
+ glEnable(GL_BLEND);
}
/* restore line-width */
@@ -2050,7 +2019,9 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
/* lamp drawing messes with matrices, could be handled smarter... but this works */
(dob->ob->type == OB_LAMP) ||
(dob->type == OB_DUPLIGROUP && dob->animated) ||
- !(bb_tmp = BKE_object_boundbox_get(dob->ob)))
+ !(bb_tmp = BKE_object_boundbox_get(dob->ob)) ||
+ draw_glsl_material(scene, dob->ob, v3d, dt) ||
+ (base->object == OBACT && v3d->flag2 & V3D_SOLID_MATCAP))
{
// printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
use_displist = false;
@@ -3025,12 +2996,12 @@ static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, A
/* draw darkened background color. no alpha because border render does
* partial redraw and will not redraw the area behind this info bar */
float alpha = 1.0f - fill_color[3];
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
- Camera *ca = v3d->camera->data;
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
- if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT))
- alpha *= (1.0f - ca->passepartalpha);
+ if (camera) {
+ if (camera->flag & CAM_SHOWPASSEPARTOUT) {
+ alpha *= (1.0f - camera->passepartalpha);
+ }
}
UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 80e5d194d45..36c6df75461 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -992,15 +992,14 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* switch from camera view when: */
if (vod->rv3d->persp != RV3D_PERSP) {
-
- if (U.uiflag & USER_AUTOPERSP) {
+ if (vod->rv3d->persp == RV3D_CAMOB) {
+ view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, vod->rv3d->lpersp);
+ }
+ else if ((U.uiflag & USER_AUTOPERSP) && RV3D_VIEW_IS_AXIS(vod->rv3d->view)) {
if (!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
vod->rv3d->persp = RV3D_PERSP;
}
}
- else if (vod->rv3d->persp == RV3D_CAMOB) {
- view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, vod->rv3d->lpersp);
- }
ED_region_tag_redraw(vod->ar);
}
@@ -2464,7 +2463,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
float min[3], max[3];
- bool change = false;
+ bool changed = false;
if (center) {
/* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
@@ -2479,7 +2478,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
for (base = scene->base.first; base; base = base->next) {
if (BASE_VISIBLE(v3d, base)) {
- change = true;
+ changed = true;
if (skip_camera && base->object == v3d->camera) {
continue;
@@ -2488,7 +2487,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
BKE_object_minmax(base->object, min, max, false);
}
}
- if (!change) {
+ if (!changed) {
ED_region_tag_redraw(ar);
/* TODO - should this be cancel?
* I think no, because we always move the cursor, with or without
@@ -3344,20 +3343,19 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
return;
}
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
-
- if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO : RV3D_PERSP;
- else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo;
+ if (U.uiflag & USER_AUTOPERSP) {
+ rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo;
+ }
+ else if (rv3d->persp == RV3D_CAMOB) {
+ rv3d->persp = perspo;
+ }
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
rv3d->ofs, new_quat, NULL, NULL,
smooth_viewtx);
}
else {
-
- if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO : RV3D_PERSP;
- else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo;
-
ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
NULL, new_quat, NULL, NULL,
smooth_viewtx);
@@ -3891,6 +3889,35 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
ot->flag = 0;
}
+static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+{
+ eViewNavigation_Method mode = U.navigation_mode;
+
+ switch (mode) {
+ case VIEW_NAVIGATION_FLY:
+ WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL);
+ break;
+ case VIEW_NAVIGATION_WALK:
+ default:
+ WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL);
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_navigate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Navigation";
+ ot->description = "Interactively navigate around the scene (uses the mode (walk/fly) preference)";
+ ot->idname = "VIEW3D_OT_navigate";
+
+ /* api callbacks */
+ ot->invoke = view3d_navigate_invoke;
+ ot->poll = ED_operator_view3d_active;
+}
+
/* ******************** add background image operator **************** */
@@ -4144,16 +4171,17 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
}
else {
- const float dx = ((float)(mval[0] - (ar->winx / 2))) * zfac / (ar->winx / 2);
- const float dy = ((float)(mval[1] - (ar->winy / 2))) * zfac / (ar->winy / 2);
- const float fz = (rv3d->persmat[0][3] * fp[0] +
- rv3d->persmat[1][3] * fp[1] +
- rv3d->persmat[2][3] * fp[2] +
- rv3d->persmat[3][3]) / zfac;
-
- fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + rv3d->persinv[2][0] * fz) - rv3d->ofs[0];
- fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + rv3d->persinv[2][1] * fz) - rv3d->ofs[1];
- fp[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy + rv3d->persinv[2][2] * fz) - rv3d->ofs[2];
+ float tvec[3];
+
+ tvec[0] = ((float)(mval[0] - (ar->winx / 2))) * zfac / (ar->winx / 2);
+ tvec[1] = ((float)(mval[1] - (ar->winy / 2))) * zfac / (ar->winy / 2);
+ tvec[2] = (rv3d->persmat[0][3] * fp[0] +
+ rv3d->persmat[1][3] * fp[1] +
+ rv3d->persmat[2][3] * fp[2] +
+ rv3d->persmat[3][3]) / zfac;
+
+ mul_mat3_m4_v3(rv3d->persinv, tvec);
+ sub_v3_v3v3(fp, tvec, rv3d->ofs);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 373e57d5708..5f8962a4e90 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -28,35 +28,29 @@
//#define NDOF_FLY_DEBUG
//#define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */
-#include "DNA_anim_types.h"
-#include "DNA_scene_types.h"
+
#include "DNA_object_types.h"
-#include "DNA_camera_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_depsgraph.h" /* for fly mode updating */
-
#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "PIL_time.h" /* smoothview */
#include "view3d_intern.h" /* own include */
+
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
enum {
FLY_MODAL_CANCEL = 1,
@@ -194,6 +188,8 @@ typedef struct FlyInfo {
bool use_freelook;
int mval[2]; /* latest 2D mouse values */
+ int center_mval[2]; /* center mouse values */
+ float width, height; /* camera viewport dimensions */
wmNDOFMotionData *ndof; /* latest 3D mouse values */
/* fly state state */
@@ -205,24 +201,6 @@ typedef struct FlyInfo {
float xlock_momentum, zlock_momentum; /* nicer dynamics */
float grid; /* world scale 1.0 default */
- /* root most parent */
- Object *root_parent;
-
- /* backup values */
- float dist_backup; /* backup the views distance since we use a zero dist for fly mode */
- float ofs_backup[3]; /* backup the views offset in case the user cancels flying in non camera mode */
-
- /* backup the views quat in case the user cancels flying in non camera mode.
- * (quat for view, eul for camera) */
- float rot_backup[4];
- short persp_backup; /* remember if were ortho or not, only used for restoring the view if it was a ortho view */
-
- /* are we flying an ortho camera in perspective view,
- * which was originally in ortho view?
- * could probably figure it out but better be explicit */
- bool is_ortho_cam;
- void *obtfm; /* backup the objects transform */
-
/* compare between last state */
double time_lastwheel; /* used to accelerate when using the mousewheel a lot */
double time_lastdraw; /* time between draws */
@@ -232,23 +210,34 @@ typedef struct FlyInfo {
/* use for some lag */
float dvec_prev[3]; /* old for some lag */
- /* for parenting calculation */
- float view_mat_prev[4][4];
+ struct View3DCameraControl *v3d_camera_control;
} FlyInfo;
static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
FlyInfo *fly = arg;
+ rctf viewborder;
+ int xoff, yoff;
+ float x1, x2, y1, y2;
+
+ if (fly->scene->camera) {
+ ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ xoff = viewborder.xmin;
+ yoff = viewborder.ymin;
+ }
+ else {
+ xoff = 0;
+ yoff = 0;
+ }
/* draws 4 edge brackets that frame the safe area where the
* mouse can move during fly mode without spinning the view */
- float x1, x2, y1, y2;
- x1 = 0.45f * (float)fly->ar->winx;
- y1 = 0.45f * (float)fly->ar->winy;
- x2 = 0.55f * (float)fly->ar->winx;
- y2 = 0.55f * (float)fly->ar->winy;
+ x1 = xoff + 0.45f * fly->width;
+ y1 = yoff + 0.45f * fly->height;
+ x2 = xoff + 0.55f * fly->width;
+ y2 = yoff + 0.55f * fly->height;
cpack(0);
glBegin(GL_LINES);
@@ -283,13 +272,17 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
}
/* FlyInfo->state */
-#define FLY_RUNNING 0
-#define FLY_CANCEL 1
-#define FLY_CONFIRM 2
+enum {
+ FLY_RUNNING = 0,
+ FLY_CANCEL = 1,
+ FLY_CONFIRM = 2,
+};
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
+ rctf viewborder;
+
float upvec[3]; /* tmp */
float mat[3][3];
@@ -348,89 +341,48 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
- fly->rv3d->rflag |= RV3D_NAVIGATING; /* so we draw the corner margins */
+ fly->rv3d->rflag |= RV3D_NAVIGATING;
/* detect whether to start with Z locking */
- upvec[0] = 1.0f;
- upvec[1] = 0.0f;
- upvec[2] = 0.0f;
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
copy_m3_m4(mat, fly->rv3d->viewinv);
mul_m3_v3(mat, upvec);
if (fabsf(upvec[2]) < 0.1f) {
fly->zlock = FLY_AXISLOCK_STATE_IDLE;
}
- upvec[0] = 0;
- upvec[1] = 0;
- upvec[2] = 0;
- fly->persp_backup = fly->rv3d->persp;
- fly->dist_backup = fly->rv3d->dist;
+ fly->v3d_camera_control = ED_view3d_cameracontrol_aquire(
+ fly->scene, fly->v3d, fly->rv3d,
+ (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
- /* check for flying ortho camera - which we cant support well
- * we _could_ also check for an ortho camera but this is easier */
- if ((fly->rv3d->persp == RV3D_CAMOB) &&
- (fly->rv3d->is_persp == false))
- {
- ((Camera *)fly->v3d->camera->data)->type = CAM_PERSP;
- fly->is_ortho_cam = true;
- }
-
- if (fly->rv3d->persp == RV3D_CAMOB) {
- Object *ob_back;
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (fly->root_parent = fly->v3d->camera->parent)) {
- while (fly->root_parent->parent)
- fly->root_parent = fly->root_parent->parent;
- ob_back = fly->root_parent;
- }
- else {
- ob_back = fly->v3d->camera;
- }
-
- /* store the original camera loc and rot */
- fly->obtfm = BKE_object_tfm_backup(ob_back);
+ /* calculate center */
+ if (fly->scene->camera) {
+ ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
- BKE_object_where_is_calc(fly->scene, fly->v3d->camera);
- negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]);
+ fly->width = BLI_rctf_size_x(&viewborder);
+ fly->height = BLI_rctf_size_y(&viewborder);
- fly->rv3d->dist = 0.0;
+ fly->center_mval[0] = viewborder.xmin + fly->width / 2;
+ fly->center_mval[1] = viewborder.ymin + fly->height / 2;
}
else {
- /* perspective or ortho */
- if (fly->rv3d->persp == RV3D_ORTHO)
- fly->rv3d->persp = RV3D_PERSP; /* if ortho projection, make perspective */
-
- copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat);
- copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs);
-
- /* the dist defines a vector that is infront of the offset
- * to rotate the view about.
- * this is no good for fly mode because we
- * want to rotate about the viewers center.
- * but to correct the dist removal we must
- * alter offset so the view doesn't jump. */
-
- fly->rv3d->dist = 0.0f;
-
- upvec[2] = fly->dist_backup; /* x and y are 0 */
- mul_m3_v3(mat, upvec);
- sub_v3_v3(fly->rv3d->ofs, upvec);
- /* Done with correcting for the dist */
- }
+ fly->width = fly->ar->winx;
+ fly->height = fly->ar->winy;
- ED_view3d_to_m4(fly->view_mat_prev, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist);
+ fly->center_mval[0] = fly->width / 2;
+ fly->center_mval[1] = fly->height / 2;
+ }
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
- WM_cursor_warp(win, fly->ar->winrct.xmin + fly->ar->winx / 2, fly->ar->winrct.ymin + fly->ar->winy / 2);
+ WM_cursor_warp(win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]);
return 1;
}
static int flyEnd(bContext *C, FlyInfo *fly)
{
- RegionView3D *rv3d = fly->rv3d;
- View3D *v3d = fly->v3d;
-
- float upvec[3];
+ wmWindow *win;
+ RegionView3D *rv3d;
if (fly->state == FLY_RUNNING)
return OPERATOR_RUNNING_MODAL;
@@ -439,58 +391,17 @@ static int flyEnd(bContext *C, FlyInfo *fly)
puts("\n-- fly end --");
#endif
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
-
- ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel);
-
- rv3d->dist = fly->dist_backup;
- if (fly->state == FLY_CANCEL) {
- /* Revert to original view? */
- if (fly->persp_backup == RV3D_CAMOB) { /* a camera view */
- Object *ob_back;
- ob_back = (fly->root_parent) ? fly->root_parent : fly->v3d->camera;
+ win = CTX_wm_window(C);
+ rv3d = fly->rv3d;
- /* store the original camera loc and rot */
- BKE_object_tfm_restore(ob_back, fly->obtfm);
+ WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer);
- DAG_id_tag_update(&ob_back->id, OB_RECALC_OB);
- }
- else {
- /* Non Camera we need to reset the view back to the original location bacause the user canceled*/
- copy_qt_qt(rv3d->viewquat, fly->rot_backup);
- rv3d->persp = fly->persp_backup;
- }
- /* always, is set to zero otherwise */
- copy_v3_v3(rv3d->ofs, fly->ofs_backup);
- }
- else if (fly->persp_backup == RV3D_CAMOB) { /* camera */
- DAG_id_tag_update(fly->root_parent ? &fly->root_parent->id : &v3d->camera->id, OB_RECALC_OB);
-
- /* always, is set to zero otherwise */
- copy_v3_v3(rv3d->ofs, fly->ofs_backup);
- }
- else { /* not camera */
-
- /* Apply the fly mode view */
- /* restore the dist */
- float mat[3][3];
- upvec[0] = upvec[1] = 0;
- upvec[2] = fly->dist_backup; /* x and y are 0 */
- copy_m3_m4(mat, rv3d->viewinv);
- mul_m3_v3(mat, upvec);
- add_v3_v3(rv3d->ofs, upvec);
- /* Done with correcting for the dist */
- }
+ ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel);
- if (fly->is_ortho_cam) {
- ((Camera *)fly->v3d->camera->data)->type = CAM_ORTHO;
- }
+ ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL);
rv3d->rflag &= ~RV3D_NAVIGATING;
-//XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */
- if (fly->obtfm)
- MEM_freeN(fly->obtfm);
if (fly->ndof)
MEM_freeN(fly->ndof);
@@ -633,7 +544,6 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
fly->pan_view = true;
break;
case FLY_MODAL_PAN_DISABLE:
-//XXX2.5 WM_cursor_warp(CTX_wm_window(C), cent_orig[0], cent_orig[1]);
fly->pan_view = false;
break;
@@ -739,86 +649,10 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
}
}
-static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
- const bool do_rotate, const bool do_translate)
+static void flyMoveCamera(bContext *C, FlyInfo *fly,
+ const bool do_rotate, const bool do_translate)
{
- /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
-
- View3D *v3d = fly->v3d;
- Scene *scene = fly->scene;
- ID *id_key;
-
- /* transform the parent or the camera? */
- if (fly->root_parent) {
- Object *ob_update;
-
- float view_mat[4][4];
- float prev_view_imat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
-
- invert_m4_m4(prev_view_imat, fly->view_mat_prev);
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
- mul_m4_m4m4(parent_mat, diff_mat, fly->root_parent->obmat);
-
- BKE_object_apply_mat4(fly->root_parent, parent_mat, true, false);
-
- // BKE_object_where_is_calc(scene, fly->root_parent);
-
- ob_update = v3d->camera->parent;
- while (ob_update) {
- DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
- ob_update = ob_update->parent;
- }
-
- copy_m4_m4(fly->view_mat_prev, view_mat);
-
- id_key = &fly->root_parent->id;
- }
- else {
- float view_mat[4][4];
- float size_mat[4][4];
- float size_back[3];
-
- /* even though we handle the size matrix, this still changes over time */
- copy_v3_v3(size_back, v3d->camera->size);
-
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- size_to_mat4(size_mat, v3d->camera->size);
- mul_m4_m4m4(view_mat, view_mat, size_mat);
-
- BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
-
- copy_v3_v3(v3d->camera->size, size_back);
-
- id_key = &v3d->camera->id;
- }
-
- /* record the motion */
- if (autokeyframe_cfra_can_key(scene, id_key)) {
- ListBase dsources = {NULL, NULL};
-
- /* add datasource override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
-
- /* insert keyframes
- * 1) on the first frame
- * 2) on each subsequent frame
- * TODO: need to check in future that frame changed before doing this
- */
- if (do_rotate) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- }
- if (do_translate) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
- }
-
- /* free temp data */
- BLI_freelistN(&dsources);
- }
+ ED_view3d_cameracontrol_update(fly->v3d_camera_control, true, C, do_rotate, do_translate);
}
static int flyApply(bContext *C, FlyInfo *fly)
@@ -832,7 +666,6 @@ static int flyApply(bContext *C, FlyInfo *fly)
* a fly loop where the user can move move the view as if they are flying
*/
RegionView3D *rv3d = fly->rv3d;
- ARegion *ar = fly->ar;
float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
float dvec[3] = {0, 0, 0}; /* this is the direction thast added to the view offset per redraw */
@@ -843,8 +676,6 @@ static int flyApply(bContext *C, FlyInfo *fly)
float moffset[2]; /* mouse offset from the views center */
float tmp_quat[4]; /* used for rotating the view */
-// int cent_orig[2], /* view center */
-//XXX- can avoid using // cent[2], /* view center modified */
int xmargin, ymargin; /* x and y margin are define the safe area where the mouses movement wont rotate the view */
#ifdef NDOF_FLY_DEBUG
@@ -854,18 +685,14 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
#endif
- xmargin = ar->winx / 20.0f;
- ymargin = ar->winy / 20.0f;
-
- // UNUSED
- // cent_orig[0] = ar->winrct.xmin + ar->winx / 2;
- // cent_orig[1] = ar->winrct.ymin + ar->winy / 2;
+ xmargin = fly->width / 20.0f;
+ ymargin = fly->height / 20.0f;
{
/* mouse offset from the center */
- moffset[0] = fly->mval[0] - ar->winx / 2;
- moffset[1] = fly->mval[1] - ar->winy / 2;
+ moffset[0] = fly->mval[0] - fly->center_mval[0];
+ moffset[1] = fly->mval[1] - fly->center_mval[1];
/* enforce a view margin */
if (moffset[0] > xmargin) moffset[0] -= xmargin;
@@ -883,12 +710,12 @@ static int flyApply(bContext *C, FlyInfo *fly)
* the mouse moves isn't linear */
if (moffset[0]) {
- moffset[0] /= ar->winx - (xmargin * 2);
+ moffset[0] /= fly->width - (xmargin * 2);
moffset[0] *= fabsf(moffset[0]);
}
if (moffset[1]) {
- moffset[1] /= ar->winy - (ymargin * 2);
+ moffset[1] /= fly->height - (ymargin * 2);
moffset[1] *= fabsf(moffset[1]);
}
@@ -923,9 +750,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
if (fly->pan_view == true) {
/* pan only */
- dvec_tmp[0] = -moffset[0];
- dvec_tmp[1] = -moffset[1];
- dvec_tmp[2] = 0;
+ copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f);
if (fly->use_precision) {
dvec_tmp[0] *= 0.1f;
@@ -941,9 +766,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
/* rotate about the X axis- look up/down */
if (moffset[1]) {
- upvec[0] = 1;
- upvec[1] = 0;
- upvec[2] = 0;
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
mul_m3_v3(mat, upvec);
/* Rotate about the relative up vec */
axis_angle_to_quat(tmp_quat, upvec, (float)moffset[1] * time_redraw * -FLY_ROTATE_FAC);
@@ -960,9 +783,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
if (moffset[0]) {
/* if we're upside down invert the moffset */
- upvec[0] = 0.0f;
- upvec[1] = 1.0f;
- upvec[2] = 0.0f;
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
mul_m3_v3(mat, upvec);
if (upvec[2] < 0.0f)
@@ -970,14 +791,10 @@ static int flyApply(bContext *C, FlyInfo *fly)
/* make the lock vectors */
if (fly->zlock) {
- upvec[0] = 0.0f;
- upvec[1] = 0.0f;
- upvec[2] = 1.0f;
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
}
else {
- upvec[0] = 0.0f;
- upvec[1] = 1.0f;
- upvec[2] = 0.0f;
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
mul_m3_v3(mat, upvec);
}
@@ -992,18 +809,14 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
- upvec[0] = 1.0f;
- upvec[1] = 0.0f;
- upvec[2] = 0.0f;
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
mul_m3_v3(mat, upvec);
/* make sure we have some z rolling */
if (fabsf(upvec[2]) > 0.00001f) {
roll = upvec[2] * 5.0f;
- upvec[0] = 0.0f; /* rotate the view about this axis */
- upvec[1] = 0.0f;
- upvec[2] = 1.0f;
-
+ /* rotate the view about this axis */
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
mul_m3_v3(mat, upvec);
/* Rotate about the relative up vec */
axis_angle_to_quat(tmp_quat, upvec,
@@ -1020,18 +833,13 @@ static int flyApply(bContext *C, FlyInfo *fly)
/* only apply xcorrect when mouse isn't applying x rot */
if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
- upvec[0] = 0;
- upvec[1] = 0;
- upvec[2] = 1;
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
mul_m3_v3(mat, upvec);
/* make sure we have some z rolling */
if (fabsf(upvec[2]) > 0.00001f) {
roll = upvec[2] * -5.0f;
-
- upvec[0] = 1.0f; /* rotate the view about this axis */
- upvec[1] = 0.0f;
- upvec[2] = 0.0f;
-
+ /* rotate the view about this axis */
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
mul_m3_v3(mat, upvec);
/* Rotate about the relative up vec */
@@ -1073,7 +881,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
if (rv3d->persp == RV3D_CAMOB) {
- Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera;
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0;
if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0;
if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0;
@@ -1086,7 +894,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
(fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
((moffset[0] || moffset[1]) && !fly->pan_view));
const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
- flyMoveCamera(C, rv3d, fly, do_rotate, do_translate);
+ flyMoveCamera(C, fly, do_rotate, do_translate);
}
}
@@ -1149,7 +957,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
if (rv3d->persp == RV3D_CAMOB) {
/* respect camera position locks */
- Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera;
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
@@ -1223,7 +1031,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
fly->redraw = true;
if (rv3d->persp == RV3D_CAMOB) {
- flyMoveCamera(C, rv3d, fly, do_rotate, do_translate);
+ flyMoveCamera(C, fly, do_rotate, do_translate);
}
}
@@ -1269,7 +1077,7 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool do_draw = false;
FlyInfo *fly = op->customdata;
RegionView3D *rv3d = fly->rv3d;
- Object *fly_object = fly->root_parent ? fly->root_parent : fly->v3d->camera;
+ Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
fly->redraw = 0;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index a496bbba72f..fae7804f31b 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -92,6 +92,7 @@ void VIEW3D_OT_view_center_camera(struct wmOperatorType *ot);
void VIEW3D_OT_view_center_lock(struct wmOperatorType *ot);
void VIEW3D_OT_view_pan(struct wmOperatorType *ot);
void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
+void VIEW3D_OT_navigate(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_add(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot);
void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
@@ -112,6 +113,9 @@ float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]);
void view3d_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_fly(struct wmOperatorType *ot);
+/* view3d_walk.c */
+void VIEW3D_OT_walk(struct wmOperatorType *ot);
+
/* view3d_ruler.c */
void VIEW3D_OT_ruler(struct wmOperatorType *ot);
@@ -195,6 +199,7 @@ void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect);
void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
+void walk_modal_keymap(struct wmKeyConfig *keyconf);
void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
@@ -204,6 +209,20 @@ void viewdolly_modal_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_properties(struct wmOperatorType *ot);
void view3d_buttons_register(struct ARegionType *art);
+/* view3d_camera_control.c */
+struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
+ Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const bool use_parent_root);
+void ED_view3d_cameracontrol_update(
+ struct View3DCameraControl *vctrl,
+ const bool use_autokey,
+ struct bContext *C, const bool do_rotate, const bool do_translate);
+void ED_view3d_cameracontrol_release(
+ struct View3DCameraControl *vctrl,
+ const bool restore);
+Object *ED_view3d_cameracontrol_object_get(
+ struct View3DCameraControl *vctrl);
+
/* view3d_toolbar.c */
void VIEW3D_OT_toolshelf(struct wmOperatorType *ot);
void view3d_toolshelf_register(struct ARegionType *art);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index dec9085baeb..12405150267 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -46,6 +46,7 @@
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_main.h"
+#include "BKE_report.h"
#include "RNA_access.h"
@@ -76,6 +77,8 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", str, BLI_temporary_dir(), "copybuffer.blend");
BKE_copybuffer_save(str, op->reports);
+ BKE_report(op->reports, RPT_INFO, "Copied selected objects to buffer");
+
return OPERATOR_FINISHED;
}
@@ -88,7 +91,6 @@ static void VIEW3D_OT_copybuffer(wmOperatorType *ot)
ot->description = "Selected objects are saved in a temp file";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = view3d_copybuffer_exec;
ot->poll = ED_operator_view3d_active;
}
@@ -102,6 +104,8 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
+ BKE_report(op->reports, RPT_INFO, "Objects pasted from buffer");
+
return OPERATOR_FINISHED;
}
@@ -114,7 +118,6 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot)
ot->description = "Contents of copy buffer gets pasted";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = view3d_pastebuffer_exec;
ot->poll = ED_operator_view3d_active;
@@ -169,6 +172,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_localview);
WM_operatortype_append(VIEW3D_OT_game_start);
WM_operatortype_append(VIEW3D_OT_fly);
+ WM_operatortype_append(VIEW3D_OT_walk);
+ WM_operatortype_append(VIEW3D_OT_navigate);
WM_operatortype_append(VIEW3D_OT_ruler);
WM_operatortype_append(VIEW3D_OT_layers);
WM_operatortype_append(VIEW3D_OT_copybuffer);
@@ -221,7 +226,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_to_active", PADPERIOD, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_clear", PADPERIOD, KM_PRESS, KM_ALT, 0);
- WM_keymap_verify_item(keymap, "VIEW3D_OT_fly", FKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
@@ -501,6 +506,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
transform_keymap_for_space(keyconf, keymap, SPACE_VIEW3D);
fly_modal_keymap(keyconf);
+ walk_modal_keymap(keyconf);
viewrotate_modal_keymap(keyconf);
viewmove_modal_keymap(keyconf);
viewzoom_modal_keymap(keyconf);
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 288ada3f852..6aa34baeac6 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -335,7 +335,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
bGPDstroke *gps;
RulerItem *ruler_item;
const char *ruler_name = RULER_ID;
- bool change = false;
+ bool changed = false;
if (scene->gpd == NULL) {
scene->gpd = gpencil_data_addnew("GPencil");
@@ -377,16 +377,16 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
}
gps->flag = GP_STROKE_3DSPACE;
BLI_addtail(&gpf->strokes, gps);
- change = true;
+ changed = true;
}
- return change;
+ return changed;
}
static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
{
Scene *scene = CTX_data_scene(C);
- bool change = false;
+ bool changed = false;
if (scene->gpd) {
bGPDlayer *gpl;
@@ -407,7 +407,7 @@ static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
pt++;
}
ruler_item->flag |= RULERITEM_USE_ANGLE;
- change = true;
+ changed = true;
}
else if (gps->totpoints == 2) {
RulerItem *ruler_item = ruler_item_add(ruler_info);
@@ -415,14 +415,14 @@ static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
copy_v3_v3(ruler_item->co[j], &pt->x);
pt++;
}
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
/* -------------------------------------------------------------------- */
@@ -541,7 +541,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
- BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+ BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
pos[0] = co_ss[1][0] + (cap_size * 2.0f);
pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
@@ -627,7 +627,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
- BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+ BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
mid_v2_v2v2(pos, co_ss[0], co_ss[2]);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index a6ef70a5e33..a15ecb1dc1c 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -236,7 +236,7 @@ typedef struct LassoSelectUserData {
/* runtime */
int pass;
bool is_done;
- bool is_change;
+ bool is_changed;
} LassoSelectUserData;
static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
@@ -256,7 +256,7 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
/* runtime */
r_data->pass = 0;
r_data->is_done = false;
- r_data->is_change = false;
+ r_data->is_changed = false;
}
static int view3d_selectable_data(bContext *C)
@@ -357,9 +357,9 @@ static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChann
{
if (data->select) pchan->bone->flag |= BONE_SELECTED;
else pchan->bone->flag &= ~BONE_SELECTED;
- data->is_change = true;
+ data->is_changed = true;
}
- data->is_change |= is_point_done;
+ data->is_changed |= is_point_done;
}
}
static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, const bool select)
@@ -383,7 +383,7 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (data.is_change) {
+ if (data.is_changed) {
bArmature *arm = ob->data;
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
@@ -647,10 +647,10 @@ static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBo
{
if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- data->is_change = true;
+ data->is_changed = true;
}
- data->is_change |= is_point_done;
+ data->is_changed |= is_point_done;
}
}
@@ -670,7 +670,7 @@ static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], sho
armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (data.is_change) {
+ if (data.is_changed) {
bArmature *arm = vc->obedit->data;
ED_armature_sync_selection(arm->edbo);
ED_armature_validate_active(arm);
@@ -687,7 +687,7 @@ static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem
{
if (data->select) ml->flag |= SELECT;
else ml->flag &= ~SELECT;
- data->is_change = true;
+ data->is_changed = true;
}
}
static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
@@ -1003,7 +1003,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
{
const int name_index = RNA_enum_get(op->ptr, "name");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
- bool change = false;
+ bool changed = false;
const char *name = object_mouse_select_menu_data[name_index].idname;
if (!toggle) {
@@ -1011,7 +1011,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
{
if (base->flag & SELECT) {
ED_base_object_select(base, BA_DESELECT);
- change = true;
+ changed = true;
}
}
CTX_DATA_END;
@@ -1023,7 +1023,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
if (STREQ(name, base->object->id.name + 2)) {
ED_base_object_activate(C, base);
ED_base_object_select(base, BA_SELECT);
- change = true;
+ changed = true;
}
}
CTX_DATA_END;
@@ -1032,7 +1032,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
/* undo? */
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
return OPERATOR_FINISHED;
}
@@ -1454,7 +1454,7 @@ static bool mouse_select(bContext *C, const int mval[2],
if (basact->object->type == OB_CAMERA) {
if (BASACT == basact) {
int i, hitresult;
- int changed = 0;
+ bool changed = false;
for (i = 0; i < hits; i++) {
hitresult = buffer[3 + (i * 4)];
@@ -1476,7 +1476,7 @@ static bool mouse_select(bContext *C, const int mval[2],
track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase);
if (TRACK_SELECTED(track) && extend) {
- changed = 0;
+ changed = false;
BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
}
else {
@@ -1487,7 +1487,7 @@ static bool mouse_select(bContext *C, const int mval[2],
BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
if (oldsel != (TRACK_SELECTED(track) ? 1 : 0))
- changed = 1;
+ changed = true;
}
basact->flag |= SELECT;
@@ -1593,7 +1593,7 @@ typedef struct BoxSelectUserData {
/* runtime */
int pass;
bool is_done;
- bool is_change;
+ bool is_changed;
} BoxSelectUserData;
static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
@@ -1610,7 +1610,7 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
/* runtime */
r_data->pass = 0;
r_data->is_done = false;
- r_data->is_change = false;
+ r_data->is_changed = false;
}
bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
@@ -2320,7 +2320,7 @@ typedef struct CircleSelectUserData {
float radius_squared;
/* runtime */
- bool is_change;
+ bool is_changed;
} CircleSelectUserData;
static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
@@ -2336,7 +2336,7 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
r_data->radius_squared = rad * rad;
/* runtime */
- r_data->is_change = false;
+ r_data->is_changed = false;
}
static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
@@ -2579,10 +2579,10 @@ static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChan
{
if (data->select) pchan->bone->flag |= BONE_SELECTED;
else pchan->bone->flag &= ~BONE_SELECTED;
- data->is_change = true;
+ data->is_changed = true;
}
- data->is_change |= is_point_done;
+ data->is_changed |= is_point_done;
}
}
static void pose_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
@@ -2595,7 +2595,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva
pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (data.is_change) {
+ if (data.is_changed) {
bArmature *arm = vc->obact->data;
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obact);
@@ -2665,10 +2665,10 @@ static void do_circle_select_armature__doSelectBone(void *userData, struct EditB
{
if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- data->is_change = true;
+ data->is_changed = true;
}
- data->is_change |= is_point_done;
+ data->is_changed |= is_point_done;
}
}
static void armature_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
@@ -2682,7 +2682,7 @@ static void armature_circle_select(ViewContext *vc, const bool select, const int
armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if (data.is_change) {
+ if (data.is_changed) {
ED_armature_sync_selection(arm->edbo);
ED_armature_validate_active(arm);
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
@@ -2696,7 +2696,7 @@ static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
if (data->select) ml->flag |= SELECT;
else ml->flag &= ~SELECT;
- data->is_change = true;
+ data->is_changed = true;
}
}
static void mball_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
@@ -2741,7 +2741,7 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
Scene *scene = vc->scene;
const float radius_squared = rad * rad;
const float mval_fl[2] = {mval[0], mval[1]};
- bool is_change = false;
+ bool changed = false;
const int select_flag = select ? SELECT : 0;
@@ -2754,13 +2754,13 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
{
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
- is_change = true;
+ changed = true;
}
}
}
}
- return is_change;
+ return changed;
}
/* not a real operator, only for circle test */
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 25458613842..3486e930466 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -692,14 +692,14 @@ bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
/* metaballs are an exception */
if (obedit->type == OB_MBALL) {
float ob_min[3], ob_max[3];
- bool change;
+ bool changed;
- change = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
- if (change) {
+ changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
+ if (changed) {
minmax_v3v3_v3(min, max, ob_min);
minmax_v3v3_v3(min, max, ob_max);
}
- return change;
+ return changed;
}
if (ED_transverts_check_obedit(obedit))
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index e321e7c9c4b..d81ab0319e6 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -110,6 +110,16 @@ float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
else return scene->cursor;
}
+Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
+{
+ /* establish the camera object, so we can default to view mapping if anything is wrong with it */
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ return v3d->camera->data;
+ }
+ else {
+ return NULL;
+ }
+}
/* ****************** smooth view operator ****************** */
/* This operator is one of the 'timer refresh' ones like animation playback */
@@ -711,6 +721,25 @@ bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy
return params.is_ortho;
}
+/**
+ * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727]
+ */
+void ED_view3d_polygon_offset(const RegionView3D *rv3d, float dist)
+{
+ float viewdist = rv3d->dist;
+
+ /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
+ if (dist != 0.0f) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (rv3d->is_persp == false) {
+ viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
+ }
+ }
+ }
+
+ bglPolygonOffset(viewdist, dist);
+}
+
/*!
* \param rect for picking, NULL not to use.
*/
@@ -1268,16 +1297,16 @@ static int localview_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
- bool change;
+ bool changed;
if (v3d->localvd) {
- change = view3d_localview_exit(bmain, scene, sa);
+ changed = view3d_localview_exit(bmain, scene, sa);
}
else {
- change = view3d_localview_init(bmain, scene, sa, op->reports);
+ changed = view3d_localview_init(bmain, scene, sa, op->reports);
}
- if (change) {
+ if (changed) {
DAG_id_type_tag(bmain, ID_OB);
ED_area_tag_redraw(CTX_wm_area(C));
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
new file mode 100644
index 00000000000..26f942b3ecd
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -0,0 +1,1419 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Dalai Felinto, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_walk.c
+ * \ingroup spview3d
+ */
+
+/* defines VIEW3D_OT_navigate - walk modal operator */
+
+//#define NDOF_WALK_DEBUG
+//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_transform.h"
+
+#include "PIL_time.h" /* smoothview */
+
+#include "view3d_intern.h" /* own include */
+
+#define EARTH_GRAVITY 9.80668f /* m/s2 */
+
+/* prototypes */
+static float getVelocityZeroTime(float velocity);
+
+/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
+enum {
+ WALK_MODAL_CANCEL = 1,
+ WALK_MODAL_CONFIRM,
+ WALK_MODAL_DIR_FORWARD,
+ WALK_MODAL_DIR_FORWARD_STOP,
+ WALK_MODAL_DIR_BACKWARD,
+ WALK_MODAL_DIR_BACKWARD_STOP,
+ WALK_MODAL_DIR_LEFT,
+ WALK_MODAL_DIR_LEFT_STOP,
+ WALK_MODAL_DIR_RIGHT,
+ WALK_MODAL_DIR_RIGHT_STOP,
+ WALK_MODAL_DIR_UP,
+ WALK_MODAL_DIR_UP_STOP,
+ WALK_MODAL_DIR_DOWN,
+ WALK_MODAL_DIR_DOWN_STOP,
+ WALK_MODAL_FAST_ENABLE,
+ WALK_MODAL_FAST_DISABLE,
+ WALK_MODAL_SLOW_ENABLE,
+ WALK_MODAL_SLOW_DISABLE,
+ WALK_MODAL_JUMP,
+ WALK_MODAL_JUMP_STOP,
+ WALK_MODAL_TELEPORT,
+ WALK_MODAL_TOGGLE,
+ WALK_MODAL_ACCELERATE,
+ WALK_MODAL_DECELERATE,
+};
+
+enum {
+ WALK_BIT_FORWARD = 1 << 0,
+ WALK_BIT_BACKWARD = 1 << 1,
+ WALK_BIT_LEFT = 1 << 2,
+ WALK_BIT_RIGHT = 1 << 3,
+ WALK_BIT_UP = 1 << 4,
+ WALK_BIT_DOWN = 1 << 5,
+};
+
+typedef enum eWalkTeleportState {
+ WALK_TELEPORT_STATE_OFF = 0,
+ WALK_TELEPORT_STATE_ON,
+} eWalkTeleportState;
+
+typedef enum eWalkMethod {
+ WALK_MODE_FREE = 0,
+ WALK_MODE_GRAVITY,
+} eWalkMethod;
+
+typedef enum eWalkGravityState {
+ WALK_GRAVITY_STATE_OFF = 0,
+ WALK_GRAVITY_STATE_JUMP,
+ WALK_GRAVITY_STATE_START,
+ WALK_GRAVITY_STATE_ON,
+} eWalkGravityState;
+
+/* called in transform_ops.c, on each regeneration of keymaps */
+void walk_modal_keymap(wmKeyConfig *keyconf)
+{
+ static EnumPropertyItem modal_items[] = {
+ {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
+ {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
+
+ {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Move Forward", ""},
+ {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Move Backward", ""},
+ {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Move Left (Strafe)", ""},
+ {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Move Right (Strafe)", ""},
+ {WALK_MODAL_DIR_UP, "UP", 0, "Move Up", ""},
+ {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Move Down", ""},
+
+ {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""},
+ {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""},
+ {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""},
+ {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""},
+ {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""},
+ {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""},
+
+ {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"},
+
+ {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast Enable", "Move faster (walk or fly)"},
+ {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast Disable", "Resume regular speed"},
+
+ {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow Enable", "Move slower (walk or fly)"},
+ {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow Disable", "Resume regular speed"},
+
+ {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
+ {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump Stop", "Stop pushing jump"},
+
+ {0, NULL, 0, NULL, NULL}};
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items)
+ return;
+
+ keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_ANY, KM_ANY, 0, WALK_MODAL_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, WALK_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, WALK_MODAL_CONFIRM);
+
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_FAST_ENABLE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_FAST_DISABLE);
+
+ WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_SLOW_ENABLE);
+ WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_SLOW_DISABLE);
+
+ /* WASD */
+ WM_modalkeymap_add_item(keymap, WKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_FORWARD);
+ WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_BACKWARD);
+ WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_LEFT);
+ WM_modalkeymap_add_item(keymap, DKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_RIGHT);
+ WM_modalkeymap_add_item(keymap, EKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_UP);
+ WM_modalkeymap_add_item(keymap, QKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_DIR_DOWN);
+
+ WM_modalkeymap_add_item(keymap, WKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_FORWARD_STOP);
+ WM_modalkeymap_add_item(keymap, SKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_BACKWARD_STOP);
+ WM_modalkeymap_add_item(keymap, AKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_LEFT_STOP);
+ WM_modalkeymap_add_item(keymap, DKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_RIGHT_STOP);
+ WM_modalkeymap_add_item(keymap, EKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_UP_STOP);
+ WM_modalkeymap_add_item(keymap, QKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_DOWN_STOP);
+
+ WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_PRESS, 0, 0, WALK_MODAL_DIR_FORWARD);
+ WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_PRESS, 0, 0, WALK_MODAL_DIR_BACKWARD);
+ WM_modalkeymap_add_item(keymap, LEFTARROWKEY, KM_PRESS, 0, 0, WALK_MODAL_DIR_LEFT);
+ WM_modalkeymap_add_item(keymap, RIGHTARROWKEY, KM_PRESS, 0, 0, WALK_MODAL_DIR_RIGHT);
+
+ WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_FORWARD_STOP);
+ WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_BACKWARD_STOP);
+ WM_modalkeymap_add_item(keymap, LEFTARROWKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_LEFT_STOP);
+ WM_modalkeymap_add_item(keymap, RIGHTARROWKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_DIR_RIGHT_STOP);
+
+ WM_modalkeymap_add_item(keymap, TABKEY, KM_PRESS, 0, 0, WALK_MODAL_TOGGLE);
+ WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, WALK_MODAL_TOGGLE);
+
+ WM_modalkeymap_add_item(keymap, VKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_JUMP);
+ WM_modalkeymap_add_item(keymap, VKEY, KM_RELEASE, KM_ANY, 0, WALK_MODAL_JUMP_STOP);
+
+ WM_modalkeymap_add_item(keymap, SPACEKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_TELEPORT);
+ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_ANY, KM_ANY, 0, WALK_MODAL_TELEPORT);
+
+ WM_modalkeymap_add_item(keymap, PADPLUSKEY, KM_PRESS, KM_ANY, 0, WALK_MODAL_ACCELERATE);
+ WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, KM_ANY, 0, WALK_MODAL_DECELERATE);
+ WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ANY, 0, WALK_MODAL_ACCELERATE);
+ WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ANY, 0, WALK_MODAL_DECELERATE);
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
+}
+
+
+typedef struct WalkTeleport
+{
+ eWalkTeleportState state;
+ float duration; /* from user preferences */
+ float origin[3];
+ float direction[3];
+ double initial_time;
+ eWalkMethod navigation_mode; /* teleport always set FREE mode on */
+
+} WalkTeleport;
+
+typedef struct WalkInfo {
+ /* context stuff */
+ RegionView3D *rv3d;
+ View3D *v3d;
+ ARegion *ar;
+ Scene *scene;
+
+ wmTimer *timer; /* needed for redraws */
+
+ short state;
+ bool redraw;
+
+ int prev_mval[2]; /* previous 2D mouse values */
+ int center_mval[2]; /* center mouse values */
+ int moffset[2];
+ wmNDOFMotionData *ndof; /* latest 3D mouse values */
+
+ /* walk state state */
+ float base_speed; /* the base speed without run/slow down modifications */
+ float speed; /* the speed the view is moving per redraw */
+ float grid; /* world scale 1.0 default */
+
+ /* compare between last state */
+ double time_lastdraw; /* time between draws */
+
+ void *draw_handle_pixel;
+
+ /* use for some lag */
+ float dvec_prev[3]; /* old for some lag */
+
+ /* walk/fly */
+ eWalkMethod navigation_mode;
+
+ /* teleport */
+ WalkTeleport teleport;
+
+ /* look speed factor - user preferences */
+ float mouse_speed;
+
+ /* speed adjustments */
+ bool is_fast;
+ bool is_slow;
+
+ /* mouse reverse */
+ bool is_reversed;
+
+ /* gravity system */
+ eWalkGravityState gravity;
+
+ /* height to use in walk mode */
+ float view_height;
+
+ /* counting system to allow movement to continue if a direction (WASD) key is still pressed */
+ int active_directions;
+
+ float speed_jump;
+ float jump_height; /* maximum jump height */
+ float speed_factor; /* to use for fast/slow speeds */
+
+ struct View3DCameraControl *v3d_camera_control;
+
+} WalkInfo;
+
+static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg)
+{
+ /* draws an aim/cross in the center */
+ WalkInfo *walk = arg;
+
+ const int outter_length = 24;
+ const int inner_length = 14;
+ int xoff, yoff;
+ rctf viewborder;
+
+ if (walk->scene->camera) {
+ ED_view3d_calc_camera_border(walk->scene, ar, walk->v3d, walk->rv3d, &viewborder, false);
+ xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f;
+ yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f;
+ }
+ else {
+ xoff = walk->ar->winx / 2;
+ yoff = walk->ar->winy / 2;
+ }
+
+ cpack(0);
+
+ glBegin(GL_LINES);
+ /* North */
+ glVertex2i(xoff, yoff + inner_length);
+ glVertex2i(xoff, yoff + outter_length);
+
+ /* East */
+ glVertex2i(xoff + inner_length, yoff);
+ glVertex2i(xoff + outter_length, yoff);
+
+ /* South */
+ glVertex2i(xoff, yoff - inner_length);
+ glVertex2i(xoff, yoff - outter_length);
+
+ /* West */
+ glVertex2i(xoff - inner_length, yoff);
+ glVertex2i(xoff - outter_length, yoff);
+ glEnd();
+
+ /* XXX print shortcuts for modal options, and current values */
+}
+
+static void walk_navigation_mode_set(WalkInfo *walk, eWalkMethod mode)
+{
+ if (mode == WALK_MODE_FREE) {
+ walk->navigation_mode = WALK_MODE_FREE;
+ walk->gravity = WALK_GRAVITY_STATE_OFF;
+ }
+ else { /* WALK_MODE_GRAVITY */
+ walk->navigation_mode = WALK_MODE_GRAVITY;
+ walk->gravity = WALK_GRAVITY_STATE_START;
+ }
+}
+
+/**
+ * \param ray_distance Distance to the hit point
+ */
+static bool walk_floor_distance_get(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float dvec[3], float *ray_distance)
+{
+ float dummy_dist_px = 0;
+ float ray_normal[3] = {0, 0, -1}; /* down */
+ float ray_start[3];
+ float r_location[3];
+ float r_normal[3];
+ float dvec_tmp[3];
+ bool ret;
+
+ *ray_distance = TRANSFORM_DIST_MAX_RAY;
+
+ copy_v3_v3(ray_start, rv3d->viewinv[3]);
+
+ if (dvec) {
+ mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
+ add_v3_v3(ray_start, dvec_tmp);
+ }
+
+ ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
+ NULL, NULL,
+ ray_start, ray_normal, ray_distance,
+ NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);
+
+ /* artifically scale the distance to the scene size */
+ *ray_distance /= walk->grid;
+ return ret;
+}
+
+/**
+ * \param ray_distance Distance to the hit point
+ * \param r_location Location of the hit point
+ * \param r_normal Normal of the hit surface, transformed to always face the camera
+ */
+static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance)
+{
+ float dummy_dist_px = 0;
+ float ray_normal[3] = {0, 0, 1}; /* forward */
+ float ray_start[3];
+ float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
+ bool ret;
+
+ *ray_distance = TRANSFORM_DIST_MAX_RAY;
+
+ copy_v3_v3(ray_start, rv3d->viewinv[3]);
+ copy_m3_m4(mat, rv3d->viewinv);
+
+ mul_m3_v3(mat, ray_normal);
+
+ mul_v3_fl(ray_normal, -1);
+ normalize_v3(ray_normal);
+
+ ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
+ NULL, NULL,
+ ray_start, ray_normal, ray_distance,
+ NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);
+
+
+ /* dot is positive if both rays are facing the same direction */
+ if (dot_v3v3(ray_normal, r_normal) > 0) {
+ copy_v3_fl3(r_normal, -r_normal[0], -r_normal[1], -r_normal[2]);
+ }
+
+ /* artifically scale the distance to the scene size */
+ *ray_distance /= walk->grid;
+
+ return ret;
+}
+
+/* WalkInfo->state */
+enum {
+ WALK_RUNNING = 0,
+ WALK_CANCEL = 1,
+ WALK_CONFIRM = 2,
+};
+
+/* keep the previous speed until user changes userpreferences */
+static float base_speed = -1.f;
+static float userdef_speed = -1.f;
+
+static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
+{
+ wmWindow *win = CTX_wm_window(C);
+
+ walk->rv3d = CTX_wm_region_view3d(C);
+ walk->v3d = CTX_wm_view3d(C);
+ walk->ar = CTX_wm_region(C);
+ walk->scene = CTX_data_scene(C);
+
+#ifdef NDOF_WALK_DEBUG
+ puts("\n-- walk begin --");
+#endif
+
+ /* sanity check: for rare but possible case (if lib-linking the camera fails) */
+ if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) {
+ walk->rv3d->persp = RV3D_PERSP;
+ }
+
+ if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->id.lib) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library");
+ return false;
+ }
+
+ if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
+ return false;
+ }
+
+ if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
+ return false;
+ }
+
+ walk->state = WALK_RUNNING;
+
+ if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) {
+ base_speed = U.walk_navigation.walk_speed;
+ userdef_speed = U.walk_navigation.walk_speed;
+ }
+
+ walk->speed = 0.0f;
+ walk->is_fast = false;
+ walk->is_slow = false;
+ walk->grid = 1.f / walk->scene->unit.scale_length;
+
+ /* user preference settings */
+ walk->teleport.duration = U.walk_navigation.teleport_time;
+ walk->mouse_speed = U.walk_navigation.mouse_speed;
+
+ if ((U.walk_navigation.flag & USER_WALK_GRAVITY))
+ walk_navigation_mode_set(walk, WALK_MODE_GRAVITY);
+ else
+ walk_navigation_mode_set(walk, WALK_MODE_FREE);
+
+ walk->view_height = U.walk_navigation.view_height;
+ walk->jump_height = U.walk_navigation.jump_height;
+ walk->speed = U.walk_navigation.walk_speed;
+ walk->speed_factor = U.walk_navigation.walk_speed_factor;
+
+ walk->gravity = WALK_GRAVITY_STATE_OFF;
+
+ walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
+
+ walk->active_directions = 0;
+
+#ifdef NDOF_WALK_DRAW_TOOMUCH
+ walk->redraw = 1;
+#endif
+ zero_v3(walk->dvec_prev);
+
+ walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
+
+ walk->ndof = NULL;
+
+ walk->time_lastdraw = PIL_check_seconds_timer();
+
+ walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL);
+
+ walk->rv3d->rflag |= RV3D_NAVIGATING;
+
+
+ walk->v3d_camera_control = ED_view3d_cameracontrol_aquire(
+ walk->scene, walk->v3d, walk->rv3d,
+ (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
+
+ /* center the mouse */
+ walk->center_mval[0] = walk->ar->winx * 0.5f;
+ walk->center_mval[1] = walk->ar->winy * 0.5f;
+
+ copy_v2_v2_int(walk->prev_mval, walk->center_mval);
+
+ WM_cursor_warp(CTX_wm_window(C),
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+
+ /* remove the mouse cursor temporarily */
+ WM_cursor_modal_set(win, CURSOR_NONE);
+
+ return 1;
+}
+
+static int walkEnd(bContext *C, WalkInfo *walk)
+{
+ wmWindow *win;
+ RegionView3D *rv3d;
+
+ if (walk->state == WALK_RUNNING)
+ return OPERATOR_RUNNING_MODAL;
+
+#ifdef NDOF_WALK_DEBUG
+ puts("\n-- walk end --");
+#endif
+
+ win = CTX_wm_window(C);
+ rv3d = walk->rv3d;
+
+ WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer);
+
+ ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel);
+
+ ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL);
+
+ rv3d->rflag &= ~RV3D_NAVIGATING;
+
+ if (walk->ndof)
+ MEM_freeN(walk->ndof);
+
+ /* restore the cursor */
+ WM_cursor_modal_restore(win);
+
+ /* center the mouse */
+ WM_cursor_warp(win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+
+ if (walk->state == WALK_CONFIRM) {
+ MEM_freeN(walk);
+ return OPERATOR_FINISHED;
+ }
+
+ MEM_freeN(walk);
+ return OPERATOR_CANCELLED;
+}
+
+static bool wm_event_is_last_mousemove(const wmEvent *event)
+{
+ while ((event = event->next)) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const wmEvent *event)
+{
+ if (event->type == TIMER && event->customdata == walk->timer) {
+ walk->redraw = true;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+
+ walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
+ walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
+
+ copy_v2_v2_int(walk->prev_mval, event->mval);
+
+ if ((walk->center_mval[0] != event->mval[0]) ||
+ (walk->center_mval[1] != event->mval[1]))
+ {
+ walk->redraw = true;
+
+ if (wm_event_is_last_mousemove(event)) {
+ wmWindow *win = CTX_wm_window(C);
+
+#ifdef __APPLE__
+ if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
+ (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
+#endif
+ {
+ WM_cursor_warp(win,
+ walk->ar->winrct.xmin + walk->center_mval[0],
+ walk->ar->winrct.ymin + walk->center_mval[1]);
+ copy_v2_v2_int(walk->prev_mval, walk->center_mval);
+ }
+ }
+ }
+ }
+ else if (event->type == NDOF_MOTION) {
+ /* do these automagically get delivered? yes. */
+ // puts("ndof motion detected in walk mode!");
+ // static const char *tag_name = "3D mouse position";
+
+ wmNDOFMotionData *incoming_ndof = (wmNDOFMotionData *)event->customdata;
+ switch (incoming_ndof->progress) {
+ case P_STARTING:
+ /* start keeping track of 3D mouse position */
+#ifdef NDOF_WALK_DEBUG
+ puts("start keeping track of 3D mouse position");
+#endif
+ /* fall-through */
+ case P_IN_PROGRESS:
+ /* update 3D mouse position */
+#ifdef NDOF_WALK_DEBUG
+ putchar('.'); fflush(stdout);
+#endif
+ if (walk->ndof == NULL) {
+ // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
+ walk->ndof = MEM_dupallocN(incoming_ndof);
+ // walk->ndof = malloc(sizeof(wmNDOFMotionData));
+ }
+ else {
+ memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
+ }
+ break;
+ case P_FINISHING:
+ /* stop keeping track of 3D mouse position */
+#ifdef NDOF_WALK_DEBUG
+ puts("stop keeping track of 3D mouse position");
+#endif
+ if (walk->ndof) {
+ MEM_freeN(walk->ndof);
+ // free(walk->ndof);
+ walk->ndof = NULL;
+ }
+
+ /* update the time else the view will jump when 2D mouse/timer resume */
+ walk->time_lastdraw = PIL_check_seconds_timer();
+
+ break;
+ default:
+ break; /* should always be one of the above 3 */
+ }
+ }
+ /* handle modal keymap first */
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case WALK_MODAL_CANCEL:
+ walk->state = WALK_CANCEL;
+ break;
+ case WALK_MODAL_CONFIRM:
+ walk->state = WALK_CONFIRM;
+ break;
+
+ case WALK_MODAL_ACCELERATE:
+ base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
+ break;
+ case WALK_MODAL_DECELERATE:
+ base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
+ break;
+
+ /* implement WASD keys */
+ case WALK_MODAL_DIR_FORWARD:
+ walk->active_directions |= WALK_BIT_FORWARD;
+ break;
+ case WALK_MODAL_DIR_BACKWARD:
+ walk->active_directions |= WALK_BIT_BACKWARD;
+ break;
+ case WALK_MODAL_DIR_LEFT:
+ walk->active_directions |= WALK_BIT_LEFT;
+ break;
+ case WALK_MODAL_DIR_RIGHT:
+ walk->active_directions |= WALK_BIT_RIGHT;
+ break;
+ case WALK_MODAL_DIR_UP:
+ walk->active_directions |= WALK_BIT_UP;
+ break;
+ case WALK_MODAL_DIR_DOWN:
+ walk->active_directions |= WALK_BIT_DOWN;
+ break;
+
+ case WALK_MODAL_DIR_FORWARD_STOP:
+ walk->active_directions &= ~WALK_BIT_FORWARD;
+ break;
+ case WALK_MODAL_DIR_BACKWARD_STOP:
+ walk->active_directions &= ~WALK_BIT_BACKWARD;
+ break;
+ case WALK_MODAL_DIR_LEFT_STOP:
+ walk->active_directions &= ~WALK_BIT_LEFT;
+ break;
+ case WALK_MODAL_DIR_RIGHT_STOP:
+ walk->active_directions &= ~WALK_BIT_RIGHT;
+ break;
+ case WALK_MODAL_DIR_UP_STOP:
+ walk->active_directions &= ~WALK_BIT_UP;
+ break;
+ case WALK_MODAL_DIR_DOWN_STOP:
+ walk->active_directions &= ~WALK_BIT_DOWN;
+ break;
+
+ case WALK_MODAL_FAST_ENABLE:
+ walk->is_fast = true;
+ break;
+ case WALK_MODAL_FAST_DISABLE:
+ walk->is_fast = false;
+ break;
+ case WALK_MODAL_SLOW_ENABLE:
+ walk->is_slow = true;
+ break;
+ case WALK_MODAL_SLOW_DISABLE:
+ walk->is_slow = false;
+ break;
+
+#define JUMP_SPEED_MIN 1.0f
+#define JUMP_TIME_MAX 0.2f /* s */
+#define JUMP_SPEED_MAX sqrtf(2.0f * EARTH_GRAVITY * walk->jump_height)
+
+ case WALK_MODAL_JUMP_STOP:
+ if (walk->gravity == WALK_GRAVITY_STATE_JUMP) {
+ float t;
+
+ /* delta time */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+
+ /* reduce the veolocity, if JUMP wasn't hold for long enough */
+ t = min_ff(t, JUMP_TIME_MAX);
+ walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;
+
+ /* when jumping, duration is how long it takes before we start going down */
+ walk->teleport.duration = getVelocityZeroTime(walk->speed_jump);
+
+ /* no more increase of jump speed */
+ walk->gravity = WALK_GRAVITY_STATE_ON;
+ }
+ break;
+ case WALK_MODAL_JUMP:
+ if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
+ (walk->gravity == WALK_GRAVITY_STATE_OFF) &&
+ (walk->teleport.state == WALK_TELEPORT_STATE_OFF))
+ {
+ /* no need to check for ground,
+ * walk->gravity wouldn't be off
+ * if we were over a hole */
+ walk->gravity = WALK_GRAVITY_STATE_JUMP;
+ walk->speed_jump = JUMP_SPEED_MAX;
+
+ walk->teleport.initial_time = PIL_check_seconds_timer();
+ copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
+
+ /* using previous vec because WASD keys are not called when SPACE is */
+ copy_v2_v2(walk->teleport.direction, walk->dvec_prev);
+
+ /* when jumping, duration is how long it takes before we start going down */
+ walk->teleport.duration = getVelocityZeroTime(walk->speed_jump);
+ }
+
+ break;
+
+ case WALK_MODAL_TELEPORT:
+ {
+ float loc[3], nor[3];
+ float distance;
+ bool ret = walk_ray_cast(C, walk->rv3d, walk, loc, nor, &distance);
+
+ /* in case we are teleporting middle way from a jump */
+ walk->speed_jump = 0.0f;
+
+ if (ret) {
+ WalkTeleport *teleport = &walk->teleport;
+ teleport->state = WALK_TELEPORT_STATE_ON;
+ teleport->initial_time = PIL_check_seconds_timer();
+ teleport->duration = U.walk_navigation.teleport_time;
+
+ teleport->navigation_mode = walk->navigation_mode;
+ walk_navigation_mode_set(walk, WALK_MODE_FREE);
+
+ copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
+
+ /* stop the camera from a distance (camera height) */
+ normalize_v3(nor);
+ mul_v3_fl(nor, walk->view_height);
+ add_v3_v3(loc, nor);
+
+ sub_v3_v3v3(teleport->direction, loc, teleport->origin);
+ }
+ else {
+ walk->teleport.state = WALK_TELEPORT_STATE_OFF;
+ }
+ break;
+ }
+
+#undef JUMP_SPEED_MAX
+#undef JUMP_TIME_MAX
+#undef JUMP_SPEED_MIN
+
+ case WALK_MODAL_TOGGLE:
+ if (walk->navigation_mode == WALK_MODE_GRAVITY) {
+ walk_navigation_mode_set(walk, WALK_MODE_FREE);
+ }
+ else { /* WALK_MODE_FREE */
+ walk_navigation_mode_set(walk, WALK_MODE_GRAVITY);
+ }
+ break;
+ }
+ }
+}
+
+static void walkMoveCamera(bContext *C, WalkInfo *walk,
+ const bool do_rotate, const bool do_translate)
+{
+ ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate);
+}
+
+static float getFreeFallDistance(const float time)
+{
+ return EARTH_GRAVITY * (time * time) * 0.5f;
+}
+
+static float getVelocityZeroTime(float velocity)
+{
+ return velocity / EARTH_GRAVITY;
+}
+
+static int walkApply(bContext *C, WalkInfo *walk)
+{
+#define WALK_ROTATE_FAC 2.2f /* more is faster */
+#define WALK_TOP_LIMIT DEG2RADF(85.0f)
+#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
+#define WALK_MOVE_SPEED base_speed
+#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
+
+ /* walk mode - Ctrl+Shift+F
+ * a walk loop where the user can move move the view as if they are in a walk game
+ */
+ RegionView3D *rv3d = walk->rv3d;
+ ARegion *ar = walk->ar;
+
+ float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
+ float dvec[3] = {0.0f, 0.0f, 0.0f}; /* this is the direction that's added to the view offset per redraw */
+
+ /* Camera Uprighting variables */
+ float upvec[3] = {0.0f, 0.0f, 0.0f}; /* stores the view's up vector */
+
+ int moffset[2]; /* mouse offset from the views center */
+ float tmp_quat[4]; /* used for rotating the view */
+
+#ifdef NDOF_WALK_DEBUG
+ {
+ static unsigned int iteration = 1;
+ printf("walk timer %d\n", iteration++);
+ }
+#endif
+
+ {
+ /* mouse offset from the center */
+ copy_v2_v2_int(moffset, walk->moffset);
+
+ /* apply moffset so we can re-accumulate */
+ walk->moffset[0] = 0;
+ walk->moffset[1] = 0;
+
+ /* revert mouse */
+ if (walk->is_reversed) {
+ moffset[1] = -moffset[1];
+ }
+
+ /* Should we redraw? */
+ if ((walk->active_directions) ||
+ moffset[0] || moffset[1] ||
+ walk->teleport.state == WALK_TELEPORT_STATE_ON ||
+ walk->gravity != WALK_GRAVITY_STATE_OFF)
+ {
+ float dvec_tmp[3];
+
+ /* time how fast it takes for us to redraw,
+ * this is so simple scenes don't walk too fast */
+ double time_current;
+ float time_redraw;
+#ifdef NDOF_WALK_DRAW_TOOMUCH
+ walk->redraw = 1;
+#endif
+ time_current = PIL_check_seconds_timer();
+ time_redraw = (float)(time_current - walk->time_lastdraw);
+
+ walk->time_lastdraw = time_current;
+
+ /* base speed in m/s */
+ walk->speed = WALK_MOVE_SPEED;
+
+ if (walk->is_fast) {
+ walk->speed *= WALK_BOOST_FACTOR;
+ }
+ else if (walk->is_slow) {
+ walk->speed *= 1.0f / WALK_BOOST_FACTOR;
+ }
+
+ copy_m3_m4(mat, rv3d->viewinv);
+
+ {
+ /* rotate about the X axis- look up/down */
+ if (moffset[1]) {
+ float angle;
+ float y;
+
+ /* relative offset */
+ y = (float) moffset[1] / ar->winy;
+
+ /* speed factor */
+ y *= WALK_ROTATE_FAC;
+
+ /* user adjustement factor */
+ y *= walk->mouse_speed;
+
+ /* clamp the angle limits */
+ /* it ranges from 90.0f to -90.0f */
+ angle = -asin(rv3d->viewmat[2][2]);
+
+ if (angle > WALK_TOP_LIMIT && y > 0.0f)
+ y = 0.0f;
+
+ else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f)
+ y = 0.0f;
+
+ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, -y);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+ }
+
+ /* rotate about the Y axis- look left/right */
+ if (moffset[0]) {
+ float x;
+
+ /* if we're upside down invert the moffset */
+ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
+ mul_m3_v3(mat, upvec);
+
+ if (upvec[2] < 0.0f)
+ moffset[0] = -moffset[0];
+
+ /* relative offset */
+ x = (float) moffset[0] / ar->winx;
+
+ /* speed factor */
+ x *= WALK_ROTATE_FAC;
+
+ /* user adjustement factor */
+ x *= walk->mouse_speed;
+
+ copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
+
+ /* Rotate about the relative up vec */
+ axis_angle_to_quat(tmp_quat, upvec, x);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
+ }
+ }
+
+ /* WASD - 'move' translation code */
+ if ((walk->active_directions) &&
+ (walk->gravity == WALK_GRAVITY_STATE_OFF))
+ {
+
+ short direction;
+ zero_v3(dvec);
+
+ if ((walk->active_directions & WALK_BIT_FORWARD) ||
+ (walk->active_directions & WALK_BIT_BACKWARD))
+ {
+
+ direction = 0;
+
+ if ((walk->active_directions & WALK_BIT_FORWARD))
+ direction += 1;
+
+ if ((walk->active_directions & WALK_BIT_BACKWARD))
+ direction -= 1;
+
+ copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
+ mul_m3_v3(mat, dvec_tmp);
+
+ if (walk->navigation_mode == WALK_MODE_GRAVITY) {
+ dvec_tmp[2] = 0.0f;
+ }
+
+ normalize_v3(dvec_tmp);
+ add_v3_v3(dvec, dvec_tmp);
+
+ }
+
+ if ((walk->active_directions & WALK_BIT_LEFT) ||
+ (walk->active_directions & WALK_BIT_RIGHT))
+ {
+
+ direction = 0;
+
+ if ((walk->active_directions & WALK_BIT_LEFT))
+ direction += 1;
+
+ if ((walk->active_directions & WALK_BIT_RIGHT))
+ direction -= 1;
+
+ dvec_tmp[0] = direction * rv3d->viewinv[0][0];
+ dvec_tmp[1] = direction * rv3d->viewinv[0][1];
+ dvec_tmp[2] = 0.0f;
+
+ normalize_v3(dvec_tmp);
+ add_v3_v3(dvec, dvec_tmp);
+
+ }
+
+ if ((walk->active_directions & WALK_BIT_UP) ||
+ (walk->active_directions & WALK_BIT_DOWN))
+ {
+
+ if (walk->navigation_mode == WALK_MODE_FREE) {
+
+ direction = 0;
+
+ if ((walk->active_directions & WALK_BIT_UP))
+ direction -= 1;
+
+ if ((walk->active_directions & WALK_BIT_DOWN))
+ direction = 1;
+
+ copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
+ add_v3_v3(dvec, dvec_tmp);
+ }
+ }
+
+ /* apply movement */
+ mul_v3_fl(dvec, walk->speed * time_redraw);
+ }
+
+ /* stick to the floor */
+ if (walk->navigation_mode == WALK_MODE_GRAVITY &&
+ ELEM(walk->gravity,
+ WALK_GRAVITY_STATE_OFF,
+ WALK_GRAVITY_STATE_START))
+ {
+
+ bool ret;
+ float ray_distance;
+ float difference = -100.0f;
+ float fall_distance;
+
+ ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);
+
+ if (ret) {
+ difference = walk->view_height - ray_distance;
+ }
+
+ /* the distance we would fall naturally smoothly enough that we
+ can manually drop the object without activating gravity */
+ fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
+
+ if (fabsf(difference) < fall_distance) {
+ /* slope/stairs */
+ dvec[2] -= difference;
+
+ /* in case we switched from FREE to GRAVITY too close to the ground */
+ if (walk->gravity == WALK_GRAVITY_STATE_START)
+ walk->gravity = WALK_GRAVITY_STATE_OFF;
+ }
+ else {
+ /* hijack the teleport variables */
+ walk->teleport.initial_time = PIL_check_seconds_timer();
+ walk->gravity = WALK_GRAVITY_STATE_ON;
+ walk->teleport.duration = 0.0f;
+
+ copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
+ copy_v2_v2(walk->teleport.direction, dvec);
+
+ }
+ }
+
+ /* Falling or jumping) */
+ if (ELEM(walk->gravity, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
+ float t;
+ float z_old, z_new;
+ bool ret;
+ float ray_distance, difference = -100.0f;
+
+ /* delta time */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+
+ /* keep moving if we were moving */
+ copy_v2_v2(dvec, walk->teleport.direction);
+
+ z_old = walk->rv3d->viewinv[3][2];
+ z_new = walk->teleport.origin[2] - getFreeFallDistance(t) * walk->grid;
+
+ /* jump */
+ z_new += t * walk->speed_jump * walk->grid;
+
+ dvec[2] = z_old - z_new;
+
+ /* duration is the jump duration */
+ if (t > walk->teleport.duration) {
+ /* check to see if we are landing */
+ ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);
+
+ if (ret) {
+ difference = walk->view_height - ray_distance;
+ }
+
+ if (ray_distance < walk->view_height) {
+ /* quit falling */
+ dvec[2] -= difference;
+ walk->gravity = WALK_GRAVITY_STATE_OFF;
+ walk->speed_jump = 0.0f;
+ }
+ }
+ }
+
+ /* Teleport */
+ else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
+ float t; /* factor */
+ float new_loc[3];
+ float cur_loc[3];
+
+ /* linear interpolation */
+ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
+ t /= walk->teleport.duration;
+
+ /* clamp so we don't go past our limit */
+ if (t >= 1.0f) {
+ t = 1.0f;
+ walk->teleport.state = WALK_TELEPORT_STATE_OFF;
+ walk_navigation_mode_set(walk, walk->teleport.navigation_mode);
+ }
+
+ mul_v3_v3fl(new_loc, walk->teleport.direction, t);
+ add_v3_v3(new_loc, walk->teleport.origin);
+
+ copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
+ sub_v3_v3v3(dvec, cur_loc, new_loc);
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+ if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0f;
+ if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0f;
+ if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0f;
+ }
+
+ /* scale the movement to the scene size */
+ mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
+ add_v3_v3(rv3d->ofs, dvec_tmp);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ const bool do_rotate = (moffset[0] || moffset[1]);
+ const bool do_translate = (walk->speed != 0.0f);
+ walkMoveCamera(C, walk, do_rotate, do_translate);
+ }
+ }
+ else {
+ /* we're not redrawing but we need to update the time else the view will jump */
+ walk->time_lastdraw = PIL_check_seconds_timer();
+ }
+ /* end drawing */
+ copy_v3_v3(walk->dvec_prev, dvec);
+ }
+
+ return OPERATOR_FINISHED;
+#undef WALK_ROTATE_FAC
+#undef WALK_ZUP_CORRECT_FAC
+#undef WALK_ZUP_CORRECT_ACCEL
+#undef WALK_SMOOTH_FAC
+#undef WALK_TOP_LIMIT
+#undef WALK_BOTTOM_LIMIT
+#undef WALK_MOVE_SPEED
+#undef WALK_BOOST_FACTOR
+}
+
+static int walkApply_ndof(bContext *C, WalkInfo *walk)
+{
+ /* shorthand for oft-used variables */
+ wmNDOFMotionData *ndof = walk->ndof;
+ const float dt = ndof->dt;
+ RegionView3D *rv3d = walk->rv3d;
+ const int flag = U.ndof_flag;
+
+#if 0
+ bool do_rotate = (flag & NDOF_SHOULD_ROTATE) && (walk->pan_view == false);
+ bool do_translate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)) != 0;
+#endif
+
+ bool do_rotate = false;
+ bool do_translate = true;
+
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+ rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
+
+ if (do_translate) {
+ const float forward_sensitivity = 1.0f;
+ const float vertical_sensitivity = 0.4f;
+ const float lateral_sensitivity = 0.6f;
+
+ float speed = 10.0f; /* blender units per second */
+ /* ^^ this is ok for default cube scene, but should scale with.. something */
+
+ float trans[3] = {lateral_sensitivity * ndof->tvec[0],
+ vertical_sensitivity * ndof->tvec[1],
+ forward_sensitivity * ndof->tvec[2]};
+
+ if (walk->is_slow)
+ speed *= 0.2f;
+
+ mul_v3_fl(trans, speed * dt);
+
+ /* transform motion from view to world coordinates */
+ mul_qt_v3(view_inv, trans);
+
+ if (flag & NDOF_FLY_HELICOPTER) {
+ /* replace world z component with device y (yes it makes sense) */
+ trans[2] = speed * dt * vertical_sensitivity * ndof->tvec[1];
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* respect camera position locks */
+ Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+ if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
+ if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
+ if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
+ }
+
+ if (!is_zero_v3(trans)) {
+ /* move center of view opposite of hand motion (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, trans);
+ do_translate = true;
+ }
+ else {
+ do_translate = false;
+ }
+ }
+
+ if (do_rotate) {
+ const float turn_sensitivity = 1.0f;
+
+ float rotation[4];
+ float axis[3];
+ float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis);
+
+ if (fabsf(angle) > 0.0001f) {
+ do_rotate = true;
+
+ if (walk->is_slow)
+ angle *= 0.2f;
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* apply rotation to view */
+ axis_angle_to_quat(rotation, axis, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+
+ if (flag & NDOF_LOCK_HORIZON) {
+ /* force an upright viewpoint
+ * TODO: make this less... sudden */
+ float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
+ float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */
+
+ /* find new inverse since viewquat has changed */
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ /* could apply reverse rotation to existing view_inv to save a few cycles */
+
+ /* transform view vectors to world coordinates */
+ mul_qt_v3(view_inv, view_horizon);
+ mul_qt_v3(view_inv, view_direction);
+
+
+ /* find difference between view & world horizons
+ * true horizon lives in world xy plane, so look only at difference in z */
+ angle = -asinf(view_horizon[2]);
+
+#ifdef NDOF_WALK_DEBUG
+ printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle));
+#endif
+
+ /* rotate view so view horizon = world horizon */
+ axis_angle_to_quat(rotation, view_direction, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+ }
+
+ rv3d->view = RV3D_VIEW_USER;
+ }
+ else {
+ do_rotate = false;
+ }
+ }
+
+ if (do_translate || do_rotate) {
+ walk->redraw = true;
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ walkMoveCamera(C, walk, do_rotate, do_translate);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+/****** walk operator ******/
+static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ WalkInfo *walk;
+
+ if (rv3d->viewlock)
+ return OPERATOR_CANCELLED;
+
+ walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation");
+
+ op->customdata = walk;
+
+ if (initWalkInfo(C, walk, op) == false) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+
+ walkEvent(C, op, walk, event);
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void walk_cancel(bContext *C, wmOperator *op)
+{
+ WalkInfo *walk = op->customdata;
+
+ walk->state = WALK_CANCEL;
+ walkEnd(C, walk);
+ op->customdata = NULL;
+}
+
+static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int exit_code;
+ bool do_draw = false;
+ WalkInfo *walk = op->customdata;
+ RegionView3D *rv3d = walk->rv3d;
+ Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
+
+ walk->redraw = false;
+
+ walkEvent(C, op, walk, event);
+
+ if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */
+ if (event->type == NDOF_MOTION) {
+ walkApply_ndof(C, walk);
+ }
+ }
+ else if (event->type == TIMER && event->customdata == walk->timer) {
+ walkApply(C, walk);
+ }
+
+ do_draw |= walk->redraw;
+
+ exit_code = walkEnd(C, walk);
+
+ if (exit_code != OPERATOR_RUNNING_MODAL)
+ do_draw = true;
+
+ if (do_draw) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object);
+ }
+
+ // puts("redraw!"); // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ return exit_code;
+}
+
+void VIEW3D_OT_walk(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Walk Navigation";
+ ot->description = "Interactively walk around the scene";
+ ot->idname = "VIEW3D_OT_walk";
+
+ /* api callbacks */
+ ot->invoke = walk_invoke;
+ ot->cancel = walk_cancel;
+ ot->modal = walk_modal;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+}
+
+#undef EARTH_GRAVITY
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 2756685e9f6..2ae94fb6d5a 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1468,7 +1468,7 @@ int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float
t->mode = TFM_DUMMY;
- initTransInfo(C, t, NULL, NULL); // internal data, mouse, vectors
+ initTransInfo(C, t, NULL, NULL);
/* avoid doing connectivity lookups (when V3D_LOCAL is set) */
t->around = V3D_CENTER;
@@ -1758,7 +1758,7 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
ED_region_visible_rect(ar, &rect);
- BLF_width_and_height_default(printable, &printable_size[0], &printable_size[1]);
+ BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
xco = rect.xmax - (int)printable_size[0] - 10;
yco = rect.ymax - (int)printable_size[1] - 10;
@@ -1970,9 +1970,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
t->launch_event = LEFTMOUSE;
}
- if (!initTransInfo(C, t, op, event)) { /* internal data, mouse, vectors */
- return 0;
- }
+ initTransInfo(C, t, op, event);
if (t->spacetype == SPACE_VIEW3D) {
//calc_manipulator_stats(curarea);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index ab5f034c836..1e7052926b3 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -615,7 +615,7 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val
/*********************** Generics ********************************/
-int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
+void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
void postTrans(struct bContext *C, TransInfo *t);
void resetTransModal(TransInfo *t);
void resetTransRestrictions(TransInfo *t);
@@ -648,8 +648,9 @@ void initTransformOrientation(struct bContext *C, TransInfo *t);
bool createSpaceNormal(float mat[3][3], const float normal[3]);
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]);
-struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], char name[], int overwrite);
-void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *name);
+struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3],
+ const char *name, const bool overwrite);
+bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64]);
#define ORIENTATION_NONE 0
#define ORIENTATION_NORMAL 1
@@ -657,7 +658,7 @@ void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *
#define ORIENTATION_EDGE 3
#define ORIENTATION_FACE 4
-int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], int activeOnly);
+int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], const bool activeOnly);
void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 4ba87eb8c39..894145c9e9d 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -576,7 +576,15 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
{
if (t->total == 1) {
- setConstraint(t, t->data->axismtx, mode, text);
+ float axismtx[3][3];
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(axismtx, t->obedit_mat, t->data->axismtx);
+ }
+ else {
+ copy_m3_m3(axismtx, t->data->axismtx);
+ }
+
+ setConstraint(t, axismtx, mode, text);
}
else {
BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 06da1edbcdc..c41b4deca31 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -5071,7 +5071,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
/* get flags used for inserting keyframes */
flag = ANIM_get_keyframing_flags(scene, 1);
- /* add datasource override for the camera object */
+ /* add datasource override for the object */
ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
@@ -5143,6 +5143,22 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
+ /* only calculate paths if there are paths to be recalculated,
+ * assuming that since we've autokeyed the transforms this is
+ * now safe to apply...
+ *
+ * NOTE: only do this when there's context info
+ */
+ if (C && (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
+ //ED_objects_clear_paths(C); // XXX for now, don't need to clear
+ ED_objects_recalculate_paths(C, scene);
+
+ /* XXX: there's potential here for problems with unkeyed rotations/scale,
+ * but for now (until proper data-locality for baking operations),
+ * this should be a better fix for T24451 and T37755
+ */
+ }
+
/* free temp info */
BLI_freelistN(&dsources);
}
@@ -5787,7 +5803,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* do nothing */
}
else { /* Objects */
- int i, recalcObPaths = 0;
+ int i;
BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
@@ -5824,11 +5840,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* Set autokey if necessary */
if (!canceled) {
autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode);
-
- /* only calculate paths if there are paths to be recalculated */
- if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)
- recalcObPaths = 1;
}
+
/* restore rigid body transform */
if (ob->rigidbody_object && canceled) {
float ctime = BKE_scene_frame_get(t->scene);
@@ -5836,25 +5849,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
}
}
-
- /* recalculate motion paths for objects (if necessary)
- * NOTE: only do this when there is context info
- */
- if (C && recalcObPaths) {
- //ED_objects_clear_paths(C); // XXX for now, don't need to clear
- ED_objects_recalculate_paths(C, t->scene);
-
- /* recalculating the frame positions means we loose our original transform if its not auto-keyed [#24451]
- * this hack re-applies it, which is annoying, only alternatives are...
- * - don't recalc paths.
- * - have an BKE_object_handle_update() which gives is the new transform without touching the objects.
- * - only recalc paths on auto-keying.
- * - ED_objects_recalculate_paths could backup/restore transforms.
- * - re-apply the transform which is simplest in this case. (2 lines below)
- */
- t->redraw |= TREDRAW_HARD;
- transformApply(C, t);
- }
}
clear_trans_object_base_flags(t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 95b6067f2c4..0ff94fb4f1c 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1029,8 +1029,12 @@ static int initTransInfo_edit_pet_to_flag(const int proportional)
}
}
-/* the *op can be NULL */
-int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
+/**
+ * Setup internal data, mouse, vectors
+ *
+ * \note \a op and \a event can be NULL
+ */
+void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
Scene *sce = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -1321,8 +1325,6 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
setTransformViewMatrices(t);
initNumInput(&t->num);
-
- return 1;
}
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 132a46441e6..5ac97ed4e26 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -642,8 +642,9 @@ int calc_manipulator_stats(const bContext *C)
default: /* V3D_MANIP_CUSTOM */
{
float mat[3][3];
- applyTransformOrientation(C, mat, NULL);
- copy_m4_m3(rv3d->twmat, mat);
+ if (applyTransformOrientation(C, mat, NULL)) {
+ copy_m4_m3(rv3d->twmat, mat);
+ }
break;
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 106024cd3e2..3a83445ba5f 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -533,7 +533,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
}
}
- if (flags & P_OPTIONS) {
+ 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");
RNA_def_property_flag(prop, PROP_HIDDEN);
@@ -617,7 +617,7 @@ static void TRANSFORM_OT_skin_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_NO_TEXSPACE);
}
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
@@ -703,7 +703,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
/* api callbacks */
ot->invoke = transform_invoke;
- ot->exec = transform_exec;
+ // ot->exec = transform_exec; // unsupported
ot->modal = transform_modal;
ot->cancel = transform_cancel;
ot->poll = ED_operator_region_view3d_active;
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index cd6a2e6712e..be8bc460764 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -26,6 +26,7 @@
#include <string.h>
+#include <stddef.h>
#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -40,7 +41,9 @@
#include "DNA_view3d_types.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
@@ -49,6 +52,8 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_report.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
#include "BLF_translation.h"
@@ -78,15 +83,7 @@ void BIF_clearTransformOrientation(bContext *C)
static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
{
- TransformOrientation *ts = NULL;
-
- for (ts = lb->first; ts; ts = ts->next) {
- if (strncmp(ts->name, name, sizeof(ts->name) - 1) == 0) {
- return ts;
- }
- }
-
- return NULL;
+ return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
}
static bool uniqueOrientationNameCheck(void *arg, const char *name)
@@ -100,7 +97,8 @@ static void uniqueOrientationName(ListBase *lb, char *name)
sizeof(((TransformOrientation *)NULL)->name));
}
-static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(reports), char *name, int overwrite)
+static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(reports),
+ const char *name, const bool overwrite)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float mat[3][3];
@@ -111,21 +109,22 @@ static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(rep
copy_m3_m4(mat, rv3d->viewinv);
normalize_m3(mat);
- if (!name[0]) {
+ if (name[0] == 0) {
View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
/* If an object is used as camera, then this space is the same as object space! */
- BLI_strncpy(name, v3d->camera->id.name + 2, MAX_NAME);
+ name = v3d->camera->id.name + 2;
}
else {
- strcpy(name, "Custom View");
+ name = "Custom View";
}
}
return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports), char *name, int overwrite)
+static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports),
+ const char *name, const bool overwrite)
{
Base *base = CTX_data_active_base(C);
Object *ob;
@@ -141,13 +140,14 @@ static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(r
/* use object name if no name is given */
if (name[0] == 0) {
- BLI_strncpy(name, ob->id.name + 2, MAX_ID_NAME - 2);
+ name = ob->id.name + 2;
}
return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *name, int overwrite)
+static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
+ const char *name, const bool overwrite)
{
float mat[3][3];
float normal[3], plane[3];
@@ -160,13 +160,14 @@ static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, c
}
if (name[0] == 0) {
- strcpy(name, "Bone");
+ name = "Bone";
}
return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports, char *name, int overwrite)
+static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
+ const char *name, const bool overwrite)
{
float mat[3][3];
float normal[3], plane[3];
@@ -179,14 +180,15 @@ static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
}
if (name[0] == 0) {
- strcpy(name, "Curve");
+ name = "Curve";
}
return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *name, int overwrite)
+static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
+ const char *name, const bool overwrite)
{
float mat[3][3];
float normal[3], plane[3];
@@ -202,7 +204,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, c
}
if (name[0] == 0) {
- strcpy(name, "Vertex");
+ name = "Vertex";
}
break;
case ORIENTATION_EDGE:
@@ -212,7 +214,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, c
}
if (name[0] == 0) {
- strcpy(name, "Edge");
+ name = "Edge";
}
break;
case ORIENTATION_FACE:
@@ -222,7 +224,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, c
}
if (name[0] == 0) {
- strcpy(name, "Face");
+ name = "Face";
}
break;
default:
@@ -288,8 +290,9 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
return true;
}
-/* name must be a MAX_NAME length string! */
-void BIF_createTransformOrientation(bContext *C, ReportList *reports, char *name, int use_view, int use, int overwrite)
+void BIF_createTransformOrientation(bContext *C, ReportList *reports,
+ const char *name, const bool use_view,
+ const bool activate, const bool overwrite)
{
TransformOrientation *ts = NULL;
@@ -315,21 +318,25 @@ void BIF_createTransformOrientation(bContext *C, ReportList *reports, char *name
}
}
- if (use && ts != NULL) {
+ if (activate && ts != NULL) {
BIF_selectTransformOrientation(C, ts);
}
}
-TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], char name[], int overwrite)
+TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
+ const char *name, const bool overwrite)
{
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
TransformOrientation *ts = NULL;
+ char name_unique[sizeof(ts->name)];
if (overwrite) {
ts = findOrientationName(transform_spaces, name);
}
else {
- uniqueOrientationName(transform_spaces, name);
+ BLI_strncpy(name_unique, name, sizeof(name_unique));
+ uniqueOrientationName(transform_spaces, name_unique);
+ name = name_unique;
}
/* if not, create a new one */
@@ -347,29 +354,14 @@ TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], char name[],
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts;
- int i;
-
- for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
- if (ts == target) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d) {
- int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
-
- // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D
- if (selected_index == i) {
- v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
- }
- else if (selected_index > i) {
- v3d->twmode--;
- }
-
- }
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_spaces = &scene->transform_spaces;
+ const int i = BLI_findindex(transform_spaces, target);
- BLI_freelinkN(transform_spaces, ts);
- break;
- }
+ if (i != -1) {
+ Main *bmain = CTX_data_main(C);
+ BKE_screen_view3d_main_twmode_remove(&bmain->screen, scene, i);
+ BLI_freelinkN(transform_spaces, target);
}
}
@@ -379,36 +371,18 @@ void BIF_removeTransformOrientationIndex(bContext *C, int index)
TransformOrientation *ts = BLI_findlink(transform_spaces, index);
if (ts) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d) {
- int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
-
- // Transform_fix_me NEED TO DO THIS FOR ALL VIEW3D
- if (selected_index == index) {
- v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
- }
- else if (selected_index > index) {
- v3d->twmode--;
- }
-
- }
-
- BLI_freelinkN(transform_spaces, ts);
+ BIF_removeTransformOrientation(C, ts);
}
}
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
{
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- View3D *v3d = CTX_wm_view3d(C);
- TransformOrientation *ts;
- int i;
-
- for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) {
- if (ts == target) {
- v3d->twmode = V3D_MANIP_CUSTOM + i;
- break;
- }
+ const int i = BLI_findindex(transform_spaces, target);
+
+ if (i != -1) {
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->twmode = V3D_MANIP_CUSTOM + i;
}
}
@@ -422,42 +396,37 @@ void BIF_selectTransformOrientationValue(bContext *C, int orientation)
int BIF_countTransformOrientation(const bContext *C)
{
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts;
- int count = 0;
-
- for (ts = transform_spaces->first; ts; ts = ts->next) {
- count++;
- }
-
- return count;
+ return BLI_countlist(transform_spaces);
}
-void applyTransformOrientation(const bContext *C, float mat[3][3], char name[MAX_NAME])
+bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name)
{
- TransformOrientation *ts;
View3D *v3d = CTX_wm_view3d(C);
int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- int i;
-
- if (selected_index >= 0) {
- for (i = 0, ts = CTX_data_scene(C)->transform_spaces.first; ts; ts = ts->next, i++) {
- if (selected_index == i) {
-
- if (name) {
- BLI_strncpy(name, ts->name, MAX_NAME);
- }
-
- copy_m3_m3(mat, ts->mat);
- break;
- }
+
+ ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
+ TransformOrientation *ts = BLI_findlink(transform_spaces, selected_index);
+
+ BLI_assert(selected_index >= 0);
+
+ if (ts) {
+ if (r_name) {
+ BLI_strncpy(r_name, ts->name, MAX_NAME);
}
+
+ copy_m3_m3(mat, ts->mat);
+ return true;
+ }
+ else {
+ /* invalid index, can happen sometimes */
+ return false;
}
}
-static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
+static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
{
Bone *bone;
- int do_next;
+ bool do_next;
int total = 0;
for (bone = lb->first; bone; bone = bone->next) {
@@ -468,7 +437,9 @@ static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
if (bone->flag & BONE_SELECTED) {
bone->flag |= BONE_TRANSFORM;
total++;
- do_next = FALSE; // no transform on children if one parent bone is selected
+
+ /* no transform on children if one parent bone is selected */
+ do_next = false;
}
}
}
@@ -487,25 +458,25 @@ void initTransformOrientation(bContext *C, TransInfo *t)
switch (t->current_orientation) {
case V3D_MANIP_GLOBAL:
unit_m3(t->spacemtx);
- strcpy(t->spacename, IFACE_("global"));
+ BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
break;
case V3D_MANIP_GIMBAL:
unit_m3(t->spacemtx);
if (gimbal_axis(ob, t->spacemtx)) {
- strcpy(t->spacename, IFACE_("gimbal"));
+ BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
break;
}
/* fall-through */ /* no gimbal fallthrough to normal */
case V3D_MANIP_NORMAL:
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- strcpy(t->spacename, IFACE_("normal"));
+ BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE));
break;
}
/* fall-through */ /* we define 'normal' as 'local' in Object mode */
case V3D_MANIP_LOCAL:
- strcpy(t->spacename, IFACE_("local"));
+ BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
if (ob) {
copy_m3_m4(t->spacemtx, ob->obmat);
@@ -522,7 +493,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
RegionView3D *rv3d = t->ar->regiondata;
float mat[3][3];
- strcpy(t->spacename, IFACE_("view"));
+ BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
copy_m3_m4(mat, rv3d->viewinv);
normalize_m3(mat);
copy_m3_m3(t->spacemtx, mat);
@@ -532,12 +503,17 @@ void initTransformOrientation(bContext *C, TransInfo *t)
}
break;
default: /* V3D_MANIP_CUSTOM */
- applyTransformOrientation(C, t->spacemtx, t->spacename);
+ if (applyTransformOrientation(C, t->spacemtx, t->spacename)) {
+ /* pass */
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
break;
}
}
-int getTransformOrientation(const bContext *C, float normal[3], float plane[3], int activeOnly)
+int getTransformOrientation(const bContext *C, float normal[3], float plane[3], const bool activeOnly)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -601,7 +577,6 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
else if (em->bm->totvertsel == 3) {
BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
BMIter iter;
- float cotangent[3];
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
@@ -612,11 +587,37 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
v2 = eve;
}
else {
+ float no_test[3];
+
+ float tan_a[3], tan_b[3], tan_c[3];
+ float len_a, len_b, len_c;
+ const float *tan_best;
+
+
v3 = eve;
+ sub_v3_v3v3(tan_a, v2->co, v1->co);
+ sub_v3_v3v3(tan_b, v3->co, v2->co);
+ sub_v3_v3v3(tan_c, v1->co, v3->co);
+ cross_v3_v3v3(normal, tan_b, tan_a);
+
+ /* check if the normal is pointing opposite to vert normals */
+ no_test[0] = v1->no[0] + v2->no[0] + v3->no[0];
+ no_test[1] = v1->no[1] + v2->no[1] + v3->no[1];
+ no_test[2] = v1->no[2] + v2->no[2] + v3->no[2];
+ if (dot_v3v3(no_test, normal) < 0.0f) {
+ negate_v3(normal);
+ }
+
+ /* always give the plane to the 2 most distant verts */
+ len_a = len_squared_v3(tan_a);
+ len_b = len_squared_v3(tan_b);
+ len_c = len_squared_v3(tan_c);
+
+ tan_best = MAX3_PAIR(len_a, len_b, len_c,
+ tan_a, tan_b, tan_c);
+
+ copy_v3_v3(plane, tan_best);
- sub_v3_v3v3(plane, v2->co, v1->co);
- sub_v3_v3v3(cotangent, v3->co, v2->co);
- cross_v3_v3v3(normal, cotangent, plane);
break;
}
}
@@ -663,9 +664,9 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
else {
v2 = eve;
- copy_v3_v3(plane, v1->no);
- add_v3_v3(plane, v2->no);
- sub_v3_v3v3(normal, v2->co, v1->co);
+ copy_v3_v3(normal, v1->no);
+ add_v3_v3(normal, v2->no);
+ sub_v3_v3v3(plane, v2->co, v1->co);
break;
}
}
@@ -864,7 +865,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
else {
int totsel;
- totsel = count_bone_select(arm, &arm->bonebase, 1);
+ totsel = count_bone_select(arm, &arm->bonebase, true);
if (totsel) {
/* use channels to get stats */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 4cda56028ca..b7dd8b7dc13 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1972,7 +1972,7 @@ static void removeDoublesPeel(ListBase *depth_peels)
for (peel = depth_peels->first; peel; peel = peel->next) {
DepthPeel *next_peel = peel->next;
- if (next_peel && ABS(peel->depth - next_peel->depth) < 0.0015f) {
+ if (next_peel && fabsf(peel->depth - next_peel->depth) < 0.0015f) {
peel->next = next_peel->next;
if (next_peel->next) {
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 7424acd752f..0e357dc53c1 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -173,8 +173,8 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
pup = uiPupMenuBegin(C, IFACE_("Unpack File"), ICON_NONE);
layout = uiPupMenuLayout(pup);
- strcpy(line, IFACE_("Remove Pack"));
- props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ props_ptr = uiItemFullO_ptr(layout, ot, IFACE_("Remove Pack"), ICON_NONE,
+ NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_REMOVE);
RNA_string_set(&props_ptr, "id", id_name);
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 62d4b01cab7..45edbde7482 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -28,7 +28,6 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
- ../../../../intern/opennl/extern
)
set(INC_SYS
@@ -51,4 +50,11 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_OPENNL)
+ add_definitions(-DWITH_OPENNL)
+ list(APPEND INC_SYS
+ ../../../../intern/opennl/extern
+ )
+endif()
+
blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index d20ef0e70e0..9be3f395fbd 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -140,8 +140,8 @@ static void draw_uvs_shadow(Object *obedit)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- /* draws the gray mesh when painting */
- glColor3ub(112, 112, 112);
+ /* draws the mesh when painting */
+ UI_ThemeColor(TH_UV_SHADOW);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
glBegin(GL_LINE_LOOP);
@@ -694,12 +694,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
glLineWidth(1);
- col2[0] = col2[1] = col2[2] = 192; col2[3] = 255;
- glColor4ubv((unsigned char *)col2);
-
+ UI_GetThemeColor4ubv(TH_WIRE_EDIT, col2);
+ glColor4ubv((unsigned char *)col2);
+
if (me->drawflag & ME_DRAWEDGES) {
int sel, lastsel = -1;
- UI_GetThemeColor4ubv(TH_VERTEX_SELECT, col1);
+ UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
if (interpedges) {
glShadeModel(GL_SMOOTH);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 474348e84bc..afe26ed1c4e 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -640,7 +640,7 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2],
BMIter iter, liter;
MTexPoly *tf;
MLoopUV *luv;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
@@ -656,12 +656,12 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2],
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(r_min, r_max, luv->uv);
- change = true;
+ changed = true;
}
}
}
- return change;
+ return changed;
}
static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2])
@@ -699,22 +699,22 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[
static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
{
- bool change = false;
+ bool changed = false;
if (mode == V3D_CENTER) { /* bounding box */
float min[2], max[2];
if (ED_uvedit_minmax(scene, ima, obedit, min, max)) {
mid_v2_v2v2(cent, min, max);
- change = true;
+ changed = true;
}
}
else {
if (ED_uvedit_median(scene, ima, obedit, cent)) {
- change = true;
+ changed = true;
}
}
- return change;
+ return changed;
}
/************************** find nearest ****************************/
@@ -2461,7 +2461,7 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
BMIter iter, liter;
MTexPoly *tf;
MLoopUV *luv;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
@@ -2504,11 +2504,11 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
luv->flag &= ~MLOOPUV_VERTSEL;
}
- change = true;
+ changed = true;
}
}
- if (change) {
+ if (changed) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
return OPERATOR_FINISHED;
}
@@ -2796,7 +2796,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
rcti rect;
rctf rectf;
- bool change, pinned, select, extend;
+ bool changed, pinned, select, extend;
const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
(ts->selectmode == SCE_SELECT_FACE) :
(ts->uv_selectmode == UV_SELECT_FACE);
@@ -2823,7 +2823,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
/* handle face selection mode */
float cent[2];
- change = false;
+ changed = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
/* assume not touched */
@@ -2834,19 +2834,19 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
uv_poly_center(efa, cent, cd_loop_uv_offset);
if (BLI_rctf_isect_pt_v(&rectf, cent)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
- change = true;
+ changed = true;
}
}
}
/* (de)selects all tagged faces and deals with sticky modes */
- if (change) {
+ if (changed) {
uv_select_flush_from_tag_face(sima, scene, obedit, select);
}
}
else {
/* other selection modes */
- change = true;
+ changed = true;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
@@ -2871,7 +2871,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
}
}
- if (change) {
+ if (changed) {
uv_select_sync_flush(ts, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -2947,7 +2947,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
float zoomx, zoomy, offset[2], ellipse[2];
int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
const bool select = (gesture_mode == GESTURE_MODAL_SELECT);
- bool change = false;
+ bool changed = false;
const bool use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
(ts->selectmode == SCE_SELECT_FACE) :
(ts->uv_selectmode == UV_SELECT_FACE);
@@ -2971,7 +2971,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
/* do selection */
if (use_face_center) {
- change = FALSE;
+ changed = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
/* assume not touched */
@@ -2980,13 +2980,13 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
uv_poly_center(efa, cent, cd_loop_uv_offset);
if (uv_inside_circle(cent, offset, ellipse)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
- change = TRUE;
+ changed = true;
}
}
}
/* (de)selects all tagged faces and deals with sticky modes */
- if (change) {
+ if (changed) {
uv_select_flush_from_tag_face(sima, scene, obedit, select);
}
}
@@ -2994,12 +2994,12 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- change |= uv_select_inside_ellipse(em, scene, select, offset, ellipse, l, luv, cd_loop_uv_offset);
+ changed |= uv_select_inside_ellipse(em, scene, select, offset, ellipse, l, luv, cd_loop_uv_offset);
}
}
}
- if (change) {
+ if (changed) {
uv_select_sync_flush(ts, em, select);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -3057,7 +3057,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
BMLoop *l;
MTexPoly *tf;
int screen_uv[2];
- bool change = false;
+ bool changed = false;
rcti rect;
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -3074,13 +3074,13 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED))
{
BM_elem_flag_enable(efa, BM_ELEM_TAG);
- change = true;
+ changed = true;
}
}
}
/* (de)selects all tagged faces and deals with sticky modes */
- if (change) {
+ if (changed) {
uv_select_flush_from_tag_face(sima, scene, obedit, select);
}
}
@@ -3096,7 +3096,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED))
{
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- change = true;
+ changed = true;
}
}
}
@@ -3104,7 +3104,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
}
}
- if (change) {
+ if (changed) {
uv_select_sync_flush(scene->toolsettings, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -3112,7 +3112,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
}
}
- return change;
+ return changed;
}
static int uv_lasso_select_exec(bContext *C, wmOperator *op)
@@ -3122,14 +3122,14 @@ static int uv_lasso_select_exec(bContext *C, wmOperator *op)
if (mcords) {
bool select;
- bool change;
+ bool changed;
select = !RNA_boolean_get(op->ptr, "deselect");
- change = do_lasso_select_mesh_uv(C, mcords, mcords_tot, select);
+ changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, select);
MEM_freeN((void *)mcords);
- return change ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
return OPERATOR_PASS_THROUGH;
@@ -3184,19 +3184,19 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Image *ima = CTX_data_edit_image(C);
- bool change = false;
+ bool changed = false;
switch (RNA_enum_get(op->ptr, "target")) {
case 0:
uv_snap_cursor_to_pixels(sima);
- change = true;
+ changed = true;
break;
case 1:
- change = uv_snap_cursor_to_selection(scene, ima, obedit, sima);
+ changed = uv_snap_cursor_to_selection(scene, ima, obedit, sima);
break;
}
- if (!change)
+ if (!changed)
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, sima);
@@ -3235,7 +3235,7 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
BMIter iter, liter;
MTexPoly *tface;
MLoopUV *luv;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
@@ -3249,12 +3249,12 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2 (luv->uv, cursor);
- change = true;
+ changed = true;
}
}
}
- return change;
+ return changed;
}
static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const float offset[2])
@@ -3265,7 +3265,7 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
BMIter iter, liter;
MTexPoly *tface;
MLoopUV *luv;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
@@ -3279,15 +3279,15 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(luv->uv, offset);
- change = true;
+ changed = true;
}
}
}
- return change;
+ return changed;
}
-static int uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
+static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -3296,7 +3296,7 @@ static int uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *
BMIter iter, liter, lsubiter;
MTexPoly *tface;
MLoopUV *luv;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
@@ -3335,14 +3335,14 @@ static int uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *
if (uv_tot) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot);
- change = true;
+ changed = true;
}
}
}
}
}
- return change;
+ return changed;
}
static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
@@ -3356,7 +3356,7 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
MLoopUV *luv;
int width = 0, height = 0;
float w, h;
- bool change = false;
+ bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
@@ -3377,10 +3377,10 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
}
}
- change = true;
+ changed = true;
}
- return change;
+ return changed;
}
static int uv_snap_selection_exec(bContext *C, wmOperator *op)
@@ -3389,14 +3389,14 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Image *ima = CTX_data_edit_image(C);
- bool change = false;
+ bool changed = false;
switch (RNA_enum_get(op->ptr, "target")) {
case 0:
- change = uv_snap_uvs_to_pixels(sima, scene, obedit);
+ changed = uv_snap_uvs_to_pixels(sima, scene, obedit);
break;
case 1:
- change = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor);
+ changed = uv_snap_uvs_to_cursor(scene, ima, obedit, sima->cursor);
break;
case 2:
{
@@ -3404,16 +3404,16 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
if (uvedit_center(scene, ima, obedit, center, sima->around)) {
float offset[2];
sub_v2_v2v2(offset, sima->cursor, center);
- change = uv_snap_uvs_offset(scene, ima, obedit, offset);
+ changed = uv_snap_uvs_offset(scene, ima, obedit, offset);
}
break;
}
case 3:
- change = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit);
+ changed = uv_snap_uvs_to_adjacent_unselected(scene, ima, obedit);
break;
}
- if (!change)
+ if (!changed)
return OPERATOR_CANCELLED;
uvedit_live_unwrap_update(sima, scene, obedit);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 2d33a2d3937..e5c3510db4b 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -35,8 +35,6 @@
#include "BLI_boxpack2d.h"
#include "BLI_convexhull2d.h"
-#include "ONL_opennl.h"
-
#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
@@ -47,6 +45,10 @@
#include "BLI_sys_types.h" /* for intptr_t support */
+#ifdef WITH_OPENNL
+
+#include "ONL_opennl.h"
+
/* Utils */
#if 0
@@ -4715,3 +4717,36 @@ void param_flush_restore(ParamHandle *handle)
}
}
+#else /* WITH_OPENNL */
+
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+/* stubs */
+void param_face_add(ParamHandle *handle, ParamKey key, int nverts,
+ ParamKey *vkeys, float **co, float **uv,
+ ParamBool *pin, ParamBool *select, float normal[3]) {}
+void param_edge_set_seam(ParamHandle *handle,
+ ParamKey *vkeys) {}
+void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy) {}
+ParamHandle *param_construct_begin(void) { return NULL; }
+void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl) {}
+void param_delete(ParamHandle *handle) {}
+
+void param_stretch_begin(ParamHandle *handle) {}
+void param_stretch_blend(ParamHandle *handle, float blend) {}
+void param_stretch_iter(ParamHandle *handle) {}
+void param_stretch_end(ParamHandle *handle) {}
+
+void param_pack(ParamHandle *handle, float margin, bool do_rotate) {}
+void param_average(ParamHandle *handle) {}
+
+void param_flush(ParamHandle *handle) {}
+void param_flush_restore(ParamHandle *handle) {}
+
+void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) {}
+void param_lscm_solve(ParamHandle *handle) {}
+void param_lscm_end(ParamHandle *handle) {}
+
+#endif /* WITH_OPENNL */
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index d6bd6f466b9..ebfef08c284 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1254,18 +1254,6 @@ void UV_OT_unwrap(wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
-/* NOTE: could be generic function */
-static Camera *view3d_camera_get(View3D *v3d, RegionView3D *rv3d)
-{
- /* establish the camera object, so we can default to view mapping if anything is wrong with it */
- if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
- return v3d->camera->data;
- }
- else {
- return NULL;
- }
-}
-
/**************** Project From View operator **************/
static int uv_from_view_exec(bContext *C, wmOperator *op);
@@ -1273,7 +1261,7 @@ static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Camera *camera = view3d_camera_get(v3d, rv3d);
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
PropertyRNA *prop;
prop = RNA_struct_find_property(op->ptr, "camera_bounds");
@@ -1292,7 +1280,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Camera *camera = view3d_camera_get(v3d, rv3d);
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -1326,9 +1314,6 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
struct ProjCameraInfo *uci = BLI_uvproject_camera_info(v3d->camera, obedit->obmat,
camera_bounds ? (scene->r.xsch * scene->r.xasp) : 1.0f,
camera_bounds ? (scene->r.ysch * scene->r.yasp) : 1.0f);
-
-
- // BLI_uvproject_camera_info_scale
if (uci) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h
index ad64fce2c44..94ae0c3c348 100644
--- a/source/blender/freestyle/intern/application/AppConfig.h
+++ b/source/blender/freestyle/intern/application/AppConfig.h
@@ -29,6 +29,7 @@
*/
#include <string>
+#include <algorithm>
#include "../system/FreestyleConfig.h"
#include "../system/Precision.h"
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index c61f72295d2..81034c1502c 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -204,7 +204,6 @@ void Controller::setPassZ(float *buf, int width, int height)
void Controller::setContext(bContext *C)
{
PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter);
- assert(py_inter != 0);
py_inter->setContext(C);
}
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
index c557c2a6368..54fd39800cc 100644
--- a/source/blender/freestyle/intern/geometry/BBox.h
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -29,6 +29,7 @@
*/
#include <stdlib.h>
+#include <algorithm>
#include "BLI_utildefines.h"
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
index 2b8b4eec4dd..99ac72db028 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
@@ -104,7 +104,7 @@ PyDoc_STRVAR(ChainPredicateIterator_doc,
static int check_begin(PyObject *obj, void *v)
{
- if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ if (obj != NULL && obj != Py_None && !BPy_ViewEdge_Check(obj))
return 0;
*((PyObject **)v) = obj;
return 1;
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
index b723631f365..1a082ac93bb 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
@@ -74,7 +74,7 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc,
static int check_begin(PyObject *obj, void *v)
{
- if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ if (obj != NULL && obj != Py_None && !BPy_ViewEdge_Check(obj))
return 0;
*((PyObject **)v) = obj;
return 1;
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
index 9a4eb2b7f61..1dadfbced03 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
@@ -75,7 +75,7 @@ PyDoc_STRVAR(ChainingIterator_doc,
static int check_begin(PyObject *obj, void *v)
{
- if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ if (obj != NULL && obj != Py_None && !BPy_ViewEdge_Check(obj))
return 0;
*((PyObject **)v) = obj;
return 1;
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
index 87e05a790b4..4a45be8caa5 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
@@ -65,7 +65,7 @@ PyDoc_STRVAR(ViewEdgeIterator_doc,
static int check_begin(PyObject *obj, void *v)
{
- if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ if (obj != NULL && obj != Py_None && !BPy_ViewEdge_Check(obj))
return 0;
*((PyObject **)v) = obj;
return 1;
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
index e5478c81b40..90f41a0d0ac 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRenderer.h
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
@@ -30,6 +30,7 @@
#include <map>
#include <string.h>
+#include <algorithm>
#include <utility>
#include <vector>
diff --git a/source/blender/freestyle/intern/view_map/GridDensityProvider.h b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
index f14362e3deb..272d64dd6de 100644
--- a/source/blender/freestyle/intern/view_map/GridDensityProvider.h
+++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
@@ -29,6 +29,7 @@
*/
#include <stdexcept>
+#include <algorithm>
#include <memory>
#include "OccluderSource.h"
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
index 91d077278fb..b5d73640c11 100644
--- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -39,7 +39,7 @@ namespace Freestyle {
void ViewEdgeXBuilder::Init(ViewShape *oVShape)
{
- if (0 == oVShape)
+ if (NULL == oVShape)
return;
// for design conveniance, we store the current SShape.
@@ -527,7 +527,7 @@ FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer&
bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer)
{
- if (0 == iFaceLayer)
+ if (NULL == iFaceLayer)
return true;
if (iFaceLayer->userdata == 0)
return false;
@@ -698,7 +698,7 @@ FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe)
bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge)
{
- if (0 == iEdge)
+ if (NULL == iEdge)
return true;
if (iEdge->userdata == 0)
return false;
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 29da72a00fe..63e5f64e6bc 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -133,6 +133,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale);
void GPU_material_unbind(GPUMaterial *material);
int GPU_material_bound(GPUMaterial *material);
+struct Scene *GPU_material_scene(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
@@ -166,6 +167,7 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_OBJECT_IMAT = 4,
GPU_DYNAMIC_OBJECT_COLOR = 5,
GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 15,
+
GPU_DYNAMIC_LAMP_FIRST = 6,
GPU_DYNAMIC_LAMP_DYNVEC = 6,
GPU_DYNAMIC_LAMP_DYNCO = 7,
@@ -177,11 +179,11 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_SAMPLER_2DBUFFER = 12,
GPU_DYNAMIC_SAMPLER_2DIMAGE = 13,
GPU_DYNAMIC_SAMPLER_2DSHADOW = 14,
- GPU_DYNAMIC_LAMP_DISTANCE = 15,
- GPU_DYNAMIC_LAMP_ATT1 = 16,
- GPU_DYNAMIC_LAMP_ATT2 = 17,
- GPU_DYNAMIC_LAMP_SPOTSIZE = 18,
- GPU_DYNAMIC_LAMP_SPOTBLEND = 19,
+ GPU_DYNAMIC_LAMP_DISTANCE = 16,
+ GPU_DYNAMIC_LAMP_ATT1 = 17,
+ GPU_DYNAMIC_LAMP_ATT2 = 18,
+ GPU_DYNAMIC_LAMP_SPOTSIZE = 19,
+ GPU_DYNAMIC_LAMP_SPOTBLEND = 20,
} GPUDynamicType;
typedef enum GPUDataType {
@@ -244,6 +246,7 @@ void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float ener
void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2);
void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
int GPU_lamp_shadow_layer(GPULamp *lamp);
+GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 0d25d988df9..0dba2cd50e8 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1784,7 +1784,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
/* spot lamp */
negate_v3_v3(direction, base->object->obmat[2]);
glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
- glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0f);
+ glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f));
glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0f*la->spotblend);
}
else
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index ed7a2f4ede0..a3813ef4584 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -355,6 +355,11 @@ int GPU_material_bound(GPUMaterial *material)
return material->bound;
}
+Scene *GPU_material_scene(GPUMaterial *material)
+{
+ return material->scene;
+}
+
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
*attribs = material->attribs;
@@ -1664,8 +1669,8 @@ void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float a
void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
{
- lamp->spotsi= cosf((float)M_PI * spotsize / 360.0f);
- lamp->spotbl= (1.0f - lamp->spotsi) * spotblend;
+ lamp->spotsi = cosf(spotsize * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
}
static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
@@ -1690,11 +1695,11 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
- lamp->spotsi= la->spotsize;
+ lamp->spotsi = la->spotsize;
if (lamp->mode & LA_HALO)
- if (lamp->spotsi > 170.0f)
- lamp->spotsi = 170.0f;
- lamp->spotsi= cosf((float)M_PI*lamp->spotsi/360.0f);
+ if (lamp->spotsi > DEG2RADF(170.0f))
+ lamp->spotsi = DEG2RADF(170.0f);
+ lamp->spotsi = cosf(lamp->spotsi * 0.5f);
lamp->spotbl= (1.0f - lamp->spotsi)*la->spotblend;
lamp->k= la->k;
@@ -1953,6 +1958,48 @@ int GPU_lamp_shadow_layer(GPULamp *lamp)
return -1;
}
+GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow)
+{
+ GPUNodeLink *visifac;
+
+ *col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob);
+ visifac = lamp_get_visibility(mat, lamp, lv, dist);
+ shade_light_textures(mat, lamp, col);
+
+ if (GPU_lamp_has_shadow_buffer(lamp)) {
+ GPUNodeLink *vn, *inp;
+
+ GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &vn);
+ GPU_link(mat, "shade_inp", vn, *lv, &inp);
+ mat->dynproperty |= DYN_LAMP_PERSMAT;
+
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ GPU_link(mat, "shadows_only_vsm",
+ GPU_builtin(GPU_VIEW_POSITION),
+ GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
+ GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
+ GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias),
+ GPU_uniform(lamp->shadow_color), inp, shadow);
+ }
+ else {
+ GPU_link(mat, "shadows_only",
+ GPU_builtin(GPU_VIEW_POSITION),
+ GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
+ GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
+ GPU_uniform(&lamp->bias), GPU_uniform(lamp->shadow_color), inp, shadow);
+ }
+ }
+ else {
+ GPU_link(mat, "set_rgb_one", shadow);
+ }
+
+ /* ensure shadow buffer and lamp textures will be updated */
+ add_user_list(&mat->lamps, lamp);
+ add_user_list(&lamp->materials, mat->ma);
+
+ return visifac;
+}
+
/* export the GLSL shader */
GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 5e5fac3049c..3a4aa75aa01 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -140,7 +140,7 @@ void uv_attribute(vec2 attuv, out vec3 uv)
void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
{
local = co;
- view = normalize(local);
+ view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(local): vec3(0.0, 0.0, -1.0);
global = (viewinvmat*vec4(local, 1.0)).xyz;
orco = attorco;
uv_attribute(attuv, uv);
@@ -166,6 +166,15 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
outview = normalize(co);
}
+void lamp(vec4 col, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac)
+{
+ outcol = col;
+ outlv = lv;
+ outdist = dist;
+ outshadow = vec4(shadow, 1.0);
+ outvisifac = visifac;
+}
+
void math_add(float val1, float val2, out float outval)
{
outval = val1 + val2;
@@ -735,6 +744,21 @@ void combine_rgb(float r, float g, float b, out vec4 col)
col = vec4(r, g, b, 1.0);
}
+void separate_hsv(vec4 col, out float h, out float s, out float v)
+{
+ vec4 hsv;
+
+ rgb_to_hsv(col, hsv);
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+}
+
+void combine_hsv(float h, float s, float v, out vec4 col)
+{
+ hsv_to_rgb(vec4(h, s, v, 1.0), col);
+}
+
void output_node(vec4 rgb, float alpha, out vec4 outrgb)
{
outrgb = vec4(rgb.rgb, alpha);
@@ -1958,6 +1982,30 @@ void test_shadowbuf_vsm(vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float
}
}
+void shadows_only(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, vec3 shadowcolor, float inp, out vec3 result)
+{
+ result = vec3(1.0);
+
+ if(inp > 0.0) {
+ float shadfac;
+
+ test_shadowbuf(rco, shadowmap, shadowpersmat, shadowbias, inp, shadfac);
+ result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
+ }
+}
+
+void shadows_only_vsm(vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float shadowbias, float bleedbias, vec3 shadowcolor, float inp, out vec3 result)
+{
+ result = vec3(1.0);
+
+ if(inp > 0.0) {
+ float shadfac;
+
+ test_shadowbuf_vsm(rco, shadowmap, shadowpersmat, shadowbias, bleedbias, inp, shadfac);
+ result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
+ }
+}
+
void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec4 result)
{
@@ -2144,6 +2192,24 @@ void node_fresnel(float ior, vec3 N, vec3 I, out float result)
result = fresnel_dielectric(normalize(I), N, (gl_FrontFacing)? eta: 1.0/eta);
}
+/* layer_weight */
+
+void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing)
+{
+ /* fresnel */
+ float eta = max(1.0 - blend, 0.00001);
+ fresnel = fresnel_dielectric(normalize(I), N, (gl_FrontFacing)? 1.0/eta : eta );
+
+ /* facing */
+ facing = abs(dot(normalize(I), N));
+ if(blend != 0.5) {
+ blend = clamp(blend, 0.0, 0.99999);
+ blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend);
+ facing = pow(facing, blend);
+ }
+ facing = 1.0 - facing;
+}
+
/* gamma */
void node_gamma(vec4 col, float gamma, out vec4 outcol)
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 8af86389db3..09cdb3a4ee9 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -191,11 +191,6 @@ bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C
/* Finish GLSL-based display space conversion */
void IMB_colormanagement_finish_glsl_draw(void);
-/* Configures GLSL shader for conversion from space defined by role to scene linear space */
-bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide);
-/* Finish GLSL-based color space conversion */
-void IMB_colormanagement_finish_glsl_transform(void);
-
/* Roles */
enum {
COLOR_ROLE_SCENE_LINEAR = 0,
diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h
index 6173ffa9b78..bac46740f0f 100644
--- a/source/blender/imbuf/intern/IMB_indexer.h
+++ b/source/blender/imbuf/intern/IMB_indexer.h
@@ -72,14 +72,14 @@ struct anim_index {
struct anim_index_builder;
typedef struct anim_index_builder {
- FILE * fp;
+ FILE *fp;
char name[FILE_MAX];
char temp_name[FILE_MAX];
void *private_data;
- void (*delete_priv_data)(struct anim_index_builder * idx);
- void (*proc_frame)(struct anim_index_builder * idx,
+ void (*delete_priv_data)(struct anim_index_builder *idx);
+ void (*proc_frame)(struct anim_index_builder *idx,
unsigned char *buffer,
int data_size,
struct anim_index_entry *entry);
@@ -87,14 +87,14 @@ typedef struct anim_index_builder {
anim_index_builder *IMB_index_builder_create(const char *name);
void IMB_index_builder_add_entry(
- anim_index_builder * fp,
+ anim_index_builder *fp,
int frameno, unsigned long long seek_pos,
unsigned long long seek_pos_dts,
unsigned long long pts);
void IMB_index_builder_proc_frame(
- anim_index_builder * fp,
- unsigned char * buffer,
+ anim_index_builder *fp,
+ unsigned char *buffer,
int data_size,
int frameno, unsigned long long seek_pos,
unsigned long long seek_pos_dts,
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 63790cf7d25..271e52da1d4 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -477,7 +477,7 @@ static int startffmpeg(struct anim *anim)
const int *inv_table;
#endif
- if (anim == 0) return(-1);
+ if (anim == NULL) return(-1);
streamcount = anim->streamindex;
@@ -960,7 +960,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position,
int new_frame_index = 0; /* To quiet gcc barking... */
int old_frame_index = 0; /* To quiet gcc barking... */
- if (anim == 0) return (0);
+ if (anim == NULL) return (0);
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: pos=%d\n", position);
diff --git a/source/blender/imbuf/intern/cineon/CMakeLists.txt b/source/blender/imbuf/intern/cineon/CMakeLists.txt
index 0028cdb4701..c96db4e4a3d 100644
--- a/source/blender/imbuf/intern/cineon/CMakeLists.txt
+++ b/source/blender/imbuf/intern/cineon/CMakeLists.txt
@@ -39,12 +39,9 @@ set(INC_SYS
set(SRC
cin_debug_stuff.h
- cineonfile.h
cineonlib.h
- dpxfile.h
dpxlib.h
logImageCore.h
- logImageLib.h
logmemfile.h
cineon_dpx.c
diff --git a/source/blender/imbuf/intern/cineon/cineonfile.h b/source/blender/imbuf/intern/cineon/cineonfile.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/source/blender/imbuf/intern/cineon/cineonfile.h
+++ /dev/null
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index fddfa2618c2..b80a381ebbb 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -40,8 +40,6 @@
#include "BLI_math_base.h"
#include "BLI_utildefines.h"
-#include "logImageLib.h"
-
#include "MEM_guardedalloc.h"
/*
diff --git a/source/blender/imbuf/intern/cineon/dpxfile.h b/source/blender/imbuf/intern/cineon/dpxfile.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/source/blender/imbuf/intern/cineon/dpxfile.h
+++ /dev/null
diff --git a/source/blender/imbuf/intern/cineon/logImageLib.h b/source/blender/imbuf/intern/cineon/logImageLib.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/source/blender/imbuf/intern/cineon/logImageLib.h
+++ /dev/null
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index cf9cc0c2e6f..3c1a96e4005 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1300,21 +1300,19 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
handle->float_colorspace = init_data->float_colorspace;
}
-static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, bool *is_straight_alpha)
+static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, int start_scanline, int num_scanlines,
+ float *linear_buffer, bool *is_straight_alpha)
{
- float *linear_buffer = NULL;
-
int channels = handle->channels;
int width = handle->width;
- int height = handle->tot_line;
+ int height = num_scanlines;
+ int scanline_offset = channels * start_scanline * width;
int buffer_size = channels * width * height;
bool is_data = handle->is_data;
bool is_data_display = handle->cm_processor->is_data_result;
- linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer");
-
if (!handle->buffer) {
unsigned char *byte_buffer = handle->byte_buffer;
@@ -1326,7 +1324,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
int i;
/* first convert byte buffer to float, keep in image space */
- for (i = 0, fp = linear_buffer, cp = byte_buffer;
+ for (i = 0, fp = linear_buffer, cp = byte_buffer + scanline_offset;
i < width * height;
i++, fp += channels, cp += channels)
{
@@ -1359,7 +1357,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
const char *from_colorspace = handle->float_colorspace;
const char *to_colorspace = global_role_scene_linear;
- memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
+ memcpy(linear_buffer, handle->buffer + scanline_offset, buffer_size * sizeof(float));
if (!is_data && !is_data_display) {
IMB_colormanagement_transform(linear_buffer, width, height, channels,
@@ -1373,17 +1371,12 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
* before converting it into display byte buffer, so we need to
* make sure original's ImBuf buffers wouldn't be modified by
* using duplicated buffer here
- *
- * NOTE: MEM_dupallocN can't be used because buffer could be
- * specified as an offset inside allocated buffer
*/
- memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
+ memcpy(linear_buffer, handle->buffer + scanline_offset, buffer_size * sizeof(float));
*is_straight_alpha = false;
}
-
- return linear_buffer;
}
static void *do_display_buffer_apply_thread(void *handle_v)
@@ -1410,46 +1403,69 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
}
else {
- bool is_straight_alpha;
- float *linear_buffer = display_buffer_apply_get_linear_buffer(handle, &is_straight_alpha);
- bool predivide = is_straight_alpha == false;
+#define SCANLINE_BLOCK_SIZE 64
+ /* TODO(sergey): Instead of nasty scanline-blocking in per-scanline-block thread we might
+ * better to use generic task scheduler, but that would need extra testing
+ * before deploying into production.
+ */
- if (is_data) {
- /* special case for data buffers - no color space conversions,
- * only generate byte buffers
- */
- }
- else {
- /* apply processor */
- IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels,
- predivide);
- }
+ int scanlines = (height + SCANLINE_BLOCK_SIZE - 1) / SCANLINE_BLOCK_SIZE;
+ int i;
+ float *linear_buffer = MEM_mallocN(channels * width * SCANLINE_BLOCK_SIZE * sizeof(float),
+ "color conversion linear buffer");
+
+ for (i = 0; i < scanlines; i ++) {
+ int start_scanline = i * SCANLINE_BLOCK_SIZE;
+ int num_scanlines = (i == scanlines - 1) ?
+ (height - SCANLINE_BLOCK_SIZE * i) :
+ SCANLINE_BLOCK_SIZE;
+ int scanline_offset = channels * start_scanline * width;
+ int scanline_offset4 = 4 * start_scanline * width;
+ bool is_straight_alpha, predivide;
+
+ display_buffer_apply_get_linear_buffer(handle, start_scanline, num_scanlines,
+ linear_buffer, &is_straight_alpha);
+ predivide = is_straight_alpha == false;
+
+ if (is_data) {
+ /* special case for data buffers - no color space conversions,
+ * only generate byte buffers
+ */
+ }
+ else {
+ /* apply processor */
+ IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, num_scanlines, channels,
+ predivide);
+ }
- /* copy result to output buffers */
- if (display_buffer_byte) {
- /* do conversion */
- IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
- channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- predivide, width, height, width, width);
- }
+ /* copy result to output buffers */
+ if (display_buffer_byte) {
+ /* do conversion */
+ IMB_buffer_byte_from_float(display_buffer_byte + scanline_offset4, linear_buffer,
+ channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ predivide, width, num_scanlines, width, width);
+ }
- if (display_buffer) {
- memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
+ if (display_buffer) {
+ memcpy(display_buffer + scanline_offset, linear_buffer, width * num_scanlines * channels * sizeof(float));
- if (is_straight_alpha && channels == 4) {
- int i;
- float *fp;
+ if (is_straight_alpha && channels == 4) {
+ int i;
+ float *fp;
- for (i = 0, fp = display_buffer;
- i < width * height;
- i++, fp += channels)
- {
- straight_to_premul_v4(fp);
+ for (i = 0, fp = display_buffer;
+ i < width * num_scanlines;
+ i++, fp += channels)
+ {
+ straight_to_premul_v4(fp);
+ }
}
}
}
MEM_freeN(linear_buffer);
+
+#undef SCANLINE_BLOCK_SIZE
}
return NULL;
@@ -3132,36 +3148,3 @@ void IMB_colormanagement_finish_glsl_draw(void)
{
OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state);
}
-
-/* ** Color space conversion using GLSL shader ** */
-
-/**
- * Configures GLSL shader for conversion from space defined by role
- * to scene linear space
- *
- * Will create appropriate OCIO processor and setup GLSL shader,
- * so further 2D texture usage will use this conversion.
- *
- * Role is an pseudonym for a color space, see bottom of file
- * IMB_colormanagement.h for list of available roles.
- *
- * When there's no need to apply transform on 2D textures, use
- * IMB_colormanagement_finish_glsl_transform().
- */
-bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide)
-{
- OCIO_ConstProcessorRcPtr *processor;
- ColorSpace *colorspace;
-
- colorspace = colormanage_colorspace_get_roled(role);
-
- processor = colorspace_to_scene_linear_processor(colorspace);
-
- return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, NULL, predivide);
-}
-
-/* Finish GLSL-based color space conversion */
-void IMB_colormanagement_finish_glsl_transform(void)
-{
- OCIO_finishGLSLDraw(global_glsl_state.transform_ocio_glsl_state);
-}
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index bde17e17419..71d5f5150ad 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -232,6 +232,10 @@ void nearest_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
/* sample area entirely outside image? */
if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) {
+ if (outI)
+ outI[0] = outI[1] = outI[2] = outI[3] = 0;
+ if (outF)
+ outF[0] = outF[1] = outF[2] = outF[3] = 0.0f;
return;
}
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index fe74b8f7cce..ec9c8fdbb4d 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -275,6 +275,11 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
}
}
+int OIIO_getVersionHex(void)
+{
+ return openimageio_version();
+}
+
} // export "C"
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h
index ad11f4bcfe3..df1122584bd 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.h
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.h
@@ -39,12 +39,16 @@ extern "C" {
#include <stdio.h>
+struct ImBuf;
+
int imb_is_a_photoshop (const char *name);
int imb_save_photoshop (struct ImBuf *ibuf, const char *name, int flags);
struct ImBuf *imb_load_photoshop (const char *name, int flags, char *colorspace);
+int OIIO_getVersionHex(void);
+
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 922c865a0d5..b25a224e16c 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -36,6 +36,7 @@
#include <string>
#include <set>
#include <errno.h>
+#include <algorithm>
#include <openexr_api.h>
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 1e145347bb3..af27ea921ce 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -111,12 +111,12 @@ typedef struct ID {
struct ID *newid;
struct Library *lib;
char name[66]; /* MAX_ID_NAME */
- short pad, us;
/**
* LIB_... flags report on status of the datablock this ID belongs
* to.
*/
short flag;
+ int us;
int icon_id, pad2;
IDProperty *properties;
} ID;
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 4780b2e85de..b6d4a8c9db8 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -30,6 +30,7 @@
#ifndef __DNA_ARMATURE_TYPES_H__
#define __DNA_ARMATURE_TYPES_H__
+#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
@@ -88,7 +89,7 @@ typedef struct bArmature {
* - from the user perspective active == last selected
* - active should be ignored when not visible (hidden layer) */
- Bone *act_bone; /* active bone (when not in editmode) */
+ Bone *act_bone; /* active bone */
struct EditBone *act_edbone; /* active editbone (in editmode) */
void *sketch; /* sketch struct for etch-a-ton */
@@ -156,6 +157,10 @@ typedef enum eArmature_DeformFlag {
ARM_DEF_INVERT_VGROUP = (1<<4)
} eArmature_DeformFlag;
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison ARM_DEF_B_BONE_REST
+#endif
+
/* armature->pathflag */
// XXX deprecated... old animation system (armature only viz)
typedef enum eArmature_PathFlag {
@@ -166,6 +171,10 @@ typedef enum eArmature_PathFlag {
ARM_PATH_KFNOS = (1<<4)
} eArmature_PathFlag;
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison ARM_PATH_FNUMS ARM_PATH_KFRAS ARM_PATH_HEADS ARM_PATH_ACFRA ARM_PATH_KFNOS
+#endif
+
/* armature->ghosttype */
// XXX deprecated... old animation system (armature only viz)
typedef enum eArmature_GhostType {
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 824091dab32..86fa7058f97 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -140,7 +140,7 @@ typedef enum BrushFlags {
BRUSH_LOCK_SIZE = (1 << 20),
// BRUSH_TEXTURE_OVERLAY = (1 << 21), /* obsolete, use overlay_flags |= BRUSH_OVERLAY_PRIMARY instead */
BRUSH_EDGE_TO_EDGE = (1 << 22),
- BRUSH_RESTORE_MESH = (1 << 23),
+ BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
BRUSH_RANDOM_ROTATION = (1 << 25),
BRUSH_PLANE_TRIM = (1 << 26),
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index 1ece25c9f70..c99494ce00e 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -73,38 +73,50 @@ typedef struct Camera {
/* **************** CAMERA ********************* */
/* type */
-#define CAM_PERSP 0
-#define CAM_ORTHO 1
-#define CAM_PANO 2
+enum {
+ CAM_PERSP = 0,
+ CAM_ORTHO = 1,
+ CAM_PANO = 2,
+};
/* dtx */
-#define CAM_DTX_CENTER 1
-#define CAM_DTX_CENTER_DIAG 2
-#define CAM_DTX_THIRDS 4
-#define CAM_DTX_GOLDEN 8
-#define CAM_DTX_GOLDEN_TRI_A 16
-#define CAM_DTX_GOLDEN_TRI_B 32
-#define CAM_DTX_HARMONY_TRI_A 64
-#define CAM_DTX_HARMONY_TRI_B 128
+enum {
+ CAM_DTX_CENTER = (1 << 0),
+ CAM_DTX_CENTER_DIAG = (1 << 1),
+ CAM_DTX_THIRDS = (1 << 2),
+ CAM_DTX_GOLDEN = (1 << 3),
+ CAM_DTX_GOLDEN_TRI_A = (1 << 4),
+ CAM_DTX_GOLDEN_TRI_B = (1 << 5),
+ CAM_DTX_HARMONY_TRI_A = (1 << 6),
+ CAM_DTX_HARMONY_TRI_B = (1 << 7),
+};
/* flag */
-#define CAM_SHOWLIMITS 1
-#define CAM_SHOWMIST 2
-#define CAM_SHOWPASSEPARTOUT 4
-#define CAM_SHOWTITLESAFE 8
-#define CAM_SHOWNAME 16
-#define CAM_ANGLETOGGLE 32
-#define CAM_DS_EXPAND 64
-#define CAM_PANORAMA 128 /* deprecated */
-#define CAM_SHOWSENSOR 256
+enum {
+ CAM_SHOWLIMITS = (1 << 0),
+ CAM_SHOWMIST = (1 << 1),
+ CAM_SHOWPASSEPARTOUT = (1 << 2),
+ CAM_SHOWTITLESAFE = (1 << 3),
+ CAM_SHOWNAME = (1 << 4),
+ CAM_ANGLETOGGLE = (1 << 5),
+ CAM_DS_EXPAND = (1 << 6),
+ CAM_PANORAMA = (1 << 7), /* deprecated */
+ CAM_SHOWSENSOR = (1 << 8),
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison CAM_PANORAMA
+#endif
/* yafray: dof sampling switch */
/* #define CAM_YF_NO_QMC 512 */ /* deprecated */
/* Sensor fit */
-#define CAMERA_SENSOR_FIT_AUTO 0
-#define CAMERA_SENSOR_FIT_HOR 1
-#define CAMERA_SENSOR_FIT_VERT 2
+enum {
+ CAMERA_SENSOR_FIT_AUTO = 0,
+ CAMERA_SENSOR_FIT_HOR = 1,
+ CAMERA_SENSOR_FIT_VERT = 2,
+};
#define DEFAULT_SENSOR_WIDTH 32.0f
#define DEFAULT_SENSOR_HEIGHT 18.0f
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 0141c4b61db..24035464259 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -178,7 +178,6 @@ typedef struct Curve {
struct BoundBox *bb;
ListBase nurb; /* actual data, called splines in rna */
- ListBase disp; /* undeformed display list, used mostly for texture space calculation */
EditNurb *editnurb; /* edited data, not in file, use pointer so we can check for it */
diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h
index 842543da174..fc9dd8f06a9 100644
--- a/source/blender/makesdna/DNA_defs.h
+++ b/source/blender/makesdna/DNA_defs.h
@@ -44,6 +44,20 @@
# endif
#endif
+
+/* poison pragma */
+#ifdef DNA_DEPRECATED_ALLOW
+# define DNA_DEPRECATED_GCC_POISON 0
+#else
+ /* enable the pragma if we can */
+# ifdef __GNUC__
+# define DNA_DEPRECATED_GCC_POISON 1
+# else
+# define DNA_DEPRECATED_GCC_POISON 0
+# endif
+#endif
+
+
/* hrmf, we need a better include then this */
#include "../blenlib/BLI_sys_types.h" /* needed for int64_t only! */
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
index db16fa37b86..195c7eb4841 100644
--- a/source/blender/makesdna/DNA_freestyle_types.h
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -32,6 +32,7 @@
* \ingroup DNA
*/
+#include "DNA_defs.h"
#include "DNA_listBase.h"
#ifdef __cplusplus
@@ -126,7 +127,7 @@ typedef struct FreestyleConfig {
ListBase modules;
int mode; /* scripting, editor */
- int raycasting_algorithm; /* XXX deprecated */
+ int raycasting_algorithm DNA_DEPRECATED;
int flags; /* suggestive contours, ridges/valleys, material boundaries */
float sphere_radius;
float dkr_epsilon;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index b64fc08a47a..2bf874d3a85 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -147,14 +147,14 @@ typedef struct bGPdata {
// XXX many of these flags should be deprecated for more general ideas in 2.5
/* don't allow painting to occur at all */
// XXX is deprecated - not well understood
-#define GP_DATA_LMBPLOCK (1<<0)
+// #define GP_DATA_LMBPLOCK (1<<0)
/* show debugging info in viewport (i.e. status print) */
#define GP_DATA_DISPINFO (1<<1)
/* in Action Editor, show as expanded channel */
#define GP_DATA_EXPAND (1<<2)
/* is the block overriding all clicks? */
// XXX is deprecated - nasty old concept
-#define GP_DATA_EDITPAINT (1<<3)
+// #define GP_DATA_EDITPAINT (1<<3)
/* new strokes are added in viewport space */
#define GP_DATA_VIEWALIGN (1<<4)
/* Project into the screens Z values */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index dae520f458d..6b0299e6d50 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -32,6 +32,7 @@
#ifndef __DNA_IMAGE_TYPES_H__
#define __DNA_IMAGE_TYPES_H__
+#include "DNA_defs.h"
#include "DNA_ID.h"
#include "DNA_color_types.h" /* for color management */
@@ -122,18 +123,24 @@ typedef struct Image {
/* **************** IMAGE ********************* */
/* Image.flag */
-#define IMA_FIELDS 1
-#define IMA_STD_FIELD 2
-#define IMA_DO_PREMUL 4 /* deprecated, should not be used */
-#define IMA_REFLECT 16
-#define IMA_NOCOLLECT 32
-// #define IMA_DONE_TAG 64 // UNUSED
-#define IMA_OLD_PREMUL 128
-/*#define IMA_CM_PREDIVIDE 256*/ /* deprecated, should not be used */
-#define IMA_USED_FOR_RENDER 512
-#define IMA_USER_FRAME_IN_RANGE 1024 /* for image user, but these flags are mixed */
-#define IMA_VIEW_AS_RENDER 2048
-#define IMA_IGNORE_ALPHA 4096
+enum {
+ IMA_FIELDS = (1 << 0),
+ IMA_STD_FIELD = (1 << 1),
+ IMA_DO_PREMUL = (1 << 2), /* deprecated, should not be used */
+ IMA_REFLECT = (1 << 4),
+ IMA_NOCOLLECT = (1 << 5),
+ //IMA_DONE_TAG = (1 << 6), // UNUSED
+ IMA_OLD_PREMUL = (1 << 7),
+ // IMA_CM_PREDIVIDE = (1 << 8), /* deprecated, should not be used */
+ IMA_USED_FOR_RENDER = (1 << 9),
+ IMA_USER_FRAME_IN_RANGE = (1 << 10), /* for image user, but these flags are mixed */
+ IMA_VIEW_AS_RENDER = (1 << 11),
+ IMA_IGNORE_ALPHA = (1 << 12),
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison IMA_DO_PREMUL
+#endif
/* Image.tpageflag */
#define IMA_TILES 1
diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h
index a1b3d4265d3..b7aae005e3b 100644
--- a/source/blender/makesdna/DNA_lamp_types.h
+++ b/source/blender/makesdna/DNA_lamp_types.h
@@ -65,8 +65,8 @@ typedef struct Lamp {
short falloff_type;
short pad2;
- float clipsta, clipend, shadspotsize;
- float bias, soft, compressthresh, bleedbias, pad5[2];
+ float clipsta, clipend;
+ float bias, soft, compressthresh, bleedbias, pad5;
short bufsize, samp, buffers, filtertype;
char bufflag, buftype;
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 7cdb79232a9..b942197e52c 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -140,6 +140,10 @@ typedef struct TFace {
short mode, tile, unwrap;
} TFace;
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison TFace
+#endif
+
/* **************** MESH ********************* */
/* texflag */
@@ -164,7 +168,7 @@ typedef struct TFace {
/* me->flag */
/* #define ME_ISDONE 1 */
-#define ME_DEPRECATED 2
+/* #define ME_DEPRECATED 2 */
#define ME_TWOSIDED 4
#define ME_UVEFFECT 8
#define ME_VCOLEFFECT 16
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 1114549f2da..c370e677df0 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -358,8 +358,8 @@ enum {
/* mtface->flag */
enum {
- TF_SELECT = (1 << 0), /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
- TF_ACTIVE = (1 << 1), /* deprecated! */
+ // TF_SELECT = (1 << 0), /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
+ // TF_ACTIVE = (1 << 1), /* deprecated! */
TF_SEL1 = (1 << 2),
TF_SEL2 = (1 << 3),
TF_SEL3 = (1 << 4),
@@ -377,7 +377,7 @@ enum {
TF_CONVERTED = (1 << 5), /* tface converted to material */
TF_SHAREDCOL = (1 << 6),
- TF_TILES = (1 << 7), /* deprecated */
+ // TF_TILES = (1 << 7), /* deprecated */
TF_BILLBOARD = (1 << 8),
TF_TWOSIDE = (1 << 9),
TF_INVISIBLE = (1 << 10),
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 59ce965b582..2f89a83d42d 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -819,16 +819,21 @@ enum {
MOD_SOLIDIFY_FLIP = (1 << 5),
};
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison MOD_SOLIDIFY_RIM_MATERIAL
+#endif
+
typedef struct ScrewModifierData {
ModifierData modifier;
struct Object *ob_axis;
- int steps;
- int render_steps;
- int iter;
+ unsigned int steps;
+ unsigned int render_steps;
+ unsigned int iter;
float screw_ofs;
float angle;
- short axis;
+ char axis;
+ char pad;
short flag;
} ScrewModifierData;
@@ -838,6 +843,8 @@ enum {
MOD_SCREW_OBJECT_OFFSET = (1 << 2),
/* MOD_SCREW_OBJECT_ANGLE = (1 << 4), */
MOD_SCREW_SMOOTH_SHADING = (1 << 5),
+ MOD_SCREW_UV_STRETCH_U = (1 << 6),
+ MOD_SCREW_UV_STRETCH_V = (1 << 7),
};
typedef struct OceanModifierData {
@@ -1187,6 +1194,10 @@ enum {
MOD_TRIANGULATE_BEAUTY = (1 << 0), /* deprecated */
};
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison MOD_TRIANGULATE_BEAUTY
+#endif
+
/* Triangulate methods - NGons */
enum {
MOD_TRIANGULATE_NGON_BEAUTY = 0,
@@ -1310,4 +1321,20 @@ enum {
};
+typedef struct LaplacianDeformModifierData {
+ ModifierData modifier;
+ char anchor_grp_name[64]; /* MAX_VGROUP_NAME */
+ int total_verts, repeat;
+ float *vertexco;
+ void *cache_system; /* runtime only */
+ short flag, pad[3];
+
+} LaplacianDeformModifierData;
+
+/* Smooth modifier flags */
+enum {
+ MOD_LAPLACIANDEFORM_BIND = 1,
+};
+
+
#endif /* __DNA_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index a4510dd23fd..4f7c49a0ca3 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -153,8 +153,8 @@ typedef enum eNodeSocketFlag {
SOCK_HIDDEN = 2, /* hidden is user defined, to hide unused */
SOCK_IN_USE = 4, /* for quick check if socket is linked */
SOCK_UNAVAIL = 8, /* unavailable is for dynamic sockets */
- __SOCK_DYNAMIC = 16, /* DEPRECATED dynamic socket (can be modified by user) */
- __SOCK_INTERNAL = 32, /* DEPRECATED group socket should not be exposed */
+ // SOCK_DYNAMIC = 16, /* DEPRECATED dynamic socket (can be modified by user) */
+ // SOCK_INTERNAL = 32, /* DEPRECATED group socket should not be exposed */
SOCK_COLLAPSED = 64, /* socket collapsed in UI */
SOCK_HIDE_VALUE = 128, /* hide socket value, if it gets auto default */
SOCK_AUTO_HIDDEN__DEPRECATED = 256 /* socket hidden automatically, to distinguish from manually hidden */
@@ -227,7 +227,7 @@ typedef struct bNode {
#define NODE_TEST 256
/* node is disabled */
#define NODE_MUTED 512
-#define NODE_CUSTOM_NAME 1024 /* deprecated! */
+// #define NODE_CUSTOM_NAME 1024 /* deprecated! */
/* group node types: use const outputs by default */
#define NODE_CONST_OUTPUT (1<<11)
/* node is always behind others */
@@ -966,9 +966,15 @@ typedef struct NodeShaderNormalMap {
#define SHD_NORMAL_MAP_BLENDER_WORLD 4
/* subsurface */
-#define SHD_SUBSURFACE_COMPATIBLE 0 // Deprecated
-#define SHD_SUBSURFACE_CUBIC 1
-#define SHD_SUBSURFACE_GAUSSIAN 2
+enum {
+ SHD_SUBSURFACE_COMPATIBLE = 0, // Deprecated
+ SHD_SUBSURFACE_CUBIC = 1,
+ SHD_SUBSURFACE_GAUSSIAN = 2,
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison SHD_SUBSURFACE_COMPATIBLE
+#endif
/* blur node */
#define CMP_NODE_BLUR_ASPECT_NONE 0
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 2ff697f513f..9d07e046096 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -542,6 +542,8 @@ enum {
OB_NAVMESH = 1 << 20,
OB_HASOBSTACLE = 1 << 21,
OB_CHARACTER = 1 << 22,
+
+ OB_RECORD_ANIMATION = 1 << 23,
};
/* ob->gameflag2 */
@@ -607,7 +609,7 @@ enum {
/* ob->shapeflag */
enum {
OB_SHAPE_LOCK = 1 << 0,
- OB_SHAPE_TEMPLOCK = 1 << 1, /* deprecated */
+ // OB_SHAPE_TEMPLOCK = 1 << 1, /* deprecated */
OB_SHAPE_EDIT_MODE = 1 << 2,
};
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index b7ca3066b4f..4f4be3965ff 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -509,7 +509,7 @@ typedef struct ParticleSystem {
#define PSYS_GLOBAL_HAIR 2
#define PSYS_HAIR_DYNAMICS 4
#define PSYS_KEYED_TIMING 8
-#define PSYS_ENABLED 16 /* deprecated */
+//#define PSYS_ENABLED 16 /* deprecated */
#define PSYS_HAIR_UPDATED 32 /* signal for updating hair particle mode */
#define PSYS_DRAWING 64
#define PSYS_USE_IMAT 128
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 7aabad86809..86145de3291 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -196,7 +196,7 @@ typedef struct SceneRenderLayer {
#define SCE_LAY_SOLID 1
#define SCE_LAY_ZTRA 2
#define SCE_LAY_HALO 4
-#define SCE_LAY_EDGE 8 /* deprecated */
+// #define SCE_LAY_EDGE 8 /* deprecated */
#define SCE_LAY_SKY 16
#define SCE_LAY_STRAND 32
#define SCE_LAY_FRS 64
@@ -725,9 +725,15 @@ typedef struct GameData {
#define GAME_PLAYER_DESKTOP_RESOLUTION (1 << 1)
/* GameData.matmode */
-#define GAME_MAT_TEXFACE 0 /* deprecated */
-#define GAME_MAT_MULTITEX 1
-#define GAME_MAT_GLSL 2
+enum {
+ GAME_MAT_TEXFACE = 0, /* deprecated */
+ GAME_MAT_MULTITEX = 1,
+ GAME_MAT_GLSL = 2,
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison GAME_MAT_TEXFACE
+#endif
/* UV Paint */
#define UV_SCULPT_LOCK_BORDERS 1
@@ -770,7 +776,8 @@ typedef struct Paint {
* smooth the stroke */
int num_input_samples;
- int pad;
+ /* flags used for symmetry */
+ int symmetry_flags;
} Paint;
/* ------------------------------------------- */
@@ -919,8 +926,10 @@ typedef struct UnifiedPaintSettings {
int anchored_size;
float anchored_initial_mouse[2];
+ /* check is there an ongoing stroke right now */
+ int stroke_active;
+
/* drawing pressure */
- int draw_pressure;
float pressure_value;
/* position of mouse, used to sample the texture */
@@ -1220,7 +1229,7 @@ typedef struct Scene {
#define R_GAMMA 0x0004
#define R_ORTHO 0x0008
#define R_ENVMAP 0x0010
-#define R_EDGE 0x0020 /* deprecated */
+/*#define R_EDGE 0x0020 deprecated */
#define R_FIELDS 0x0040
#define R_FIELDSTILL 0x0080
/*#define R_RADIO 0x0100 */ /* deprecated */
@@ -1330,21 +1339,36 @@ typedef struct Scene {
/*#define R_ALPHAKEY 2*/ /* deprecated, shouldn't be used */
/* color_mgt_flag */
-#define R_COLOR_MANAGEMENT (1 << 0) /* deprecated, should only be used in versioning code only */
-/*#define R_COLOR_MANAGEMENT_PREDIVIDE (1 << 1)*/ /* deprecated, shouldn't be used */
+enum {
+ R_COLOR_MANAGEMENT = (1 << 0), /* deprecated, should only be used in versioning code only */
+ /*R_COLOR_MANAGEMENT_PREDIVIDE = (1 << 1)*/ /* deprecated, shouldn't be used */
+};
+
+#if 0 /* TODO */
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison R_COLOR_MANAGEMENT
+#endif
+#endif
/* subimtype, flag options for imtype */
-#define R_OPENEXR_HALF 1 /*deprecated*/
-#define R_OPENEXR_ZBUF 2 /*deprecated*/
-#define R_PREVIEW_JPG 4 /*deprecated*/
-#define R_CINEON_LOG 8 /*deprecated*/
-#define R_TIFF_16BIT 16 /*deprecated*/
-
-#define R_JPEG2K_12BIT 32 /* Jpeg2000 */ /*deprecated*/
-#define R_JPEG2K_16BIT 64 /*deprecated*/
-#define R_JPEG2K_YCC 128 /* when disabled use RGB */ /*deprecated*/
-#define R_JPEG2K_CINE_PRESET 256 /*deprecated*/
-#define R_JPEG2K_CINE_48FPS 512 /*deprecated*/
+enum {
+ R_OPENEXR_HALF = 1, /*deprecated*/
+ R_OPENEXR_ZBUF = 2, /*deprecated*/
+ R_PREVIEW_JPG = 4, /*deprecated*/
+ R_CINEON_LOG = 8, /*deprecated*/
+ R_TIFF_16BIT = 16, /*deprecated*/
+
+ R_JPEG2K_12BIT = 32, /* Jpeg2000 */ /*deprecated*/
+ R_JPEG2K_16BIT = 64, /*deprecated*/
+ R_JPEG2K_YCC = 128, /* when disabled use RGB */ /*deprecated*/
+ R_JPEG2K_CINE_PRESET = 256, /*deprecated*/
+ R_JPEG2K_CINE_48FPS = 512, /*deprecated*/
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison R_OPENEXR_HALF R_OPENEXR_ZBUF R_PREVIEW_JPG R_CINEON_LOG R_TIFF_16BIT
+#pragma GCC poison R_JPEG2K_12BIT R_JPEG2K_16BIT R_JPEG2K_YCC R_JPEG2K_CINE_PRESET R_JPEG2K_CINE_48FPS
+#endif
/* bake_mode: same as RE_BAKE_xxx defines */
/* bake_flag: */
@@ -1539,9 +1563,16 @@ typedef enum eVGroupSelect {
#define AUDIO_SCRUB (1<<2)
#define AUDIO_VOLUME_ANIMATED (1<<3)
-#define FFMPEG_MULTIPLEX_AUDIO 1 /* deprecated, you can choose none as audiocodec now */
-#define FFMPEG_AUTOSPLIT_OUTPUT 2
-#define FFMPEG_LOSSLESS_OUTPUT 4
+enum {
+ FFMPEG_MULTIPLEX_AUDIO = 1, /* deprecated, you can choose none as audiocodec now */
+ FFMPEG_AUTOSPLIT_OUTPUT = 2,
+ FFMPEG_LOSSLESS_OUTPUT = 4,
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison FFMPEG_MULTIPLEX_AUDIO
+#endif
+
/* Paint.flags */
typedef enum {
@@ -1550,16 +1581,31 @@ typedef enum {
PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2),
} PaintFlags;
+/* Paint.symmetry_flags
+ * (for now just a duplicate of sculpt symmetry flags) */
+typedef enum SymmetryFlags {
+ PAINT_SYMM_X = (1 << 0),
+ PAINT_SYMM_Y = (1 << 1),
+ PAINT_SYMM_Z = (1 << 2),
+ PAINT_SYMMETRY_FEATHER = (1 << 3)
+} SymmetryFlags;
+
+#define PAINT_SYMM_AXIS_ALL (PAINT_SYMM_X | PAINT_SYMM_Y | PAINT_SYMM_Z)
+
/* Sculpt.flags */
/* These can eventually be moved to paint flags? */
typedef enum SculptFlags {
+ /* deprecated, part of paint struct symmetry_flags now */
SCULPT_SYMM_X = (1 << 0),
SCULPT_SYMM_Y = (1 << 1),
SCULPT_SYMM_Z = (1 << 2),
+
SCULPT_LOCK_X = (1 << 3),
SCULPT_LOCK_Y = (1 << 4),
SCULPT_LOCK_Z = (1 << 5),
+ /* deprecated, part of paint struct symmetry_flags now */
SCULPT_SYMMETRY_FEATHER = (1 << 6),
+
SCULPT_USE_OPENMP = (1 << 7),
SCULPT_ONLY_DEFORM = (1 << 8),
SCULPT_SHOW_DIFFUSE = (1 << 9),
@@ -1568,11 +1614,17 @@ typedef enum SculptFlags {
* dynamic-topology mode */
SCULPT_DYNTOPO_SMOOTH_SHADING = (1 << 10),
- /* If set, dynamic-topology brushes will collapse short edges in
- * addition to subdividing long ones */
+ /* If set, dynamic-topology brushes will subdivide short edges */
+ SCULPT_DYNTOPO_SUBDIVIDE = (1 << 12),
+ /* If set, dynamic-topology brushes will collapse short edges */
SCULPT_DYNTOPO_COLLAPSE = (1 << 11)
} SculptFlags;
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison SCULPT_SYMM_X SCULPT_SYMM_Y SCULPT_SYMM_Z SCULPT_SYMMETRY_FEATHER
+#endif
+
+
/* ImagePaintSettings.flag */
#define IMAGEPAINT_DRAWING 1
// #define IMAGEPAINT_DRAW_TOOL 2 // deprecated
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index ec86a4739c5..6b90557113a 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -172,7 +172,7 @@ typedef struct ScrArea {
short flag;
short region_active_win; /* index of last used region of 'RGN_TYPE_WINDOW'
* runtuime variable, updated by executing operators */
- short pad;
+ char temp, pad;
struct SpaceType *type; /* callbacks for this space type */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 5dbc80c16a5..69d4693ab05 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -325,37 +325,43 @@ typedef struct SequencerScopes {
#define SEQ_NAME_MAXSTR 64
/* seq->flag */
-#define SEQ_LEFTSEL (1 << 1)
-#define SEQ_RIGHTSEL (1 << 2)
-#define SEQ_OVERLAP (1 << 3)
-#define SEQ_FILTERY (1 << 4)
-#define SEQ_MUTE (1 << 5)
-#define SEQ_MAKE_PREMUL (1 << 6) /* deprecated, used for compatibility code only */
-#define SEQ_REVERSE_FRAMES (1 << 7)
-#define SEQ_IPO_FRAME_LOCKED (1 << 8)
-#define SEQ_EFFECT_NOT_LOADED (1 << 9)
-#define SEQ_FLAG_DELETE (1 << 10)
-#define SEQ_FLIPX (1 << 11)
-#define SEQ_FLIPY (1 << 12)
-#define SEQ_MAKE_FLOAT (1 << 13)
-#define SEQ_LOCK (1 << 14)
-#define SEQ_USE_PROXY (1 << 15)
-#define SEQ_USE_TRANSFORM (1 << 16)
-#define SEQ_USE_CROP (1 << 17)
-/* #define SEQ_USE_COLOR_BALANCE (1 << 18) */ /* DEPRECATED */
-#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19)
-
-#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
-#define SEQ_USE_EFFECT_DEFAULT_FADE (1 << 22)
-#define SEQ_USE_LINEAR_MODIFIERS (1 << 23)
-
-// flags for whether those properties are animated or not
-#define SEQ_AUDIO_VOLUME_ANIMATED (1 << 24)
-#define SEQ_AUDIO_PITCH_ANIMATED (1 << 25)
-#define SEQ_AUDIO_PAN_ANIMATED (1 << 26)
-#define SEQ_AUDIO_DRAW_WAVEFORM (1 << 27)
-
-#define SEQ_INVALID_EFFECT (1 << 31)
+enum {
+ SEQ_LEFTSEL = (1 << 1),
+ SEQ_RIGHTSEL = (1 << 2),
+ SEQ_OVERLAP = (1 << 3),
+ SEQ_FILTERY = (1 << 4),
+ SEQ_MUTE = (1 << 5),
+ SEQ_MAKE_PREMUL = (1 << 6), /* deprecated, used for compatibility code only */
+ SEQ_REVERSE_FRAMES = (1 << 7),
+ SEQ_IPO_FRAME_LOCKED = (1 << 8),
+ SEQ_EFFECT_NOT_LOADED = (1 << 9),
+ SEQ_FLAG_DELETE = (1 << 10),
+ SEQ_FLIPX = (1 << 11),
+ SEQ_FLIPY = (1 << 12),
+ SEQ_MAKE_FLOAT = (1 << 13),
+ SEQ_LOCK = (1 << 14),
+ SEQ_USE_PROXY = (1 << 15),
+ SEQ_USE_TRANSFORM = (1 << 16),
+ SEQ_USE_CROP = (1 << 17),
+ /* SEQ_USE_COLOR_BALANCE = (1 << 18), */ /* DEPRECATED */
+ SEQ_USE_PROXY_CUSTOM_DIR = (1 << 19),
+
+ SEQ_USE_PROXY_CUSTOM_FILE = (1 << 21),
+ SEQ_USE_EFFECT_DEFAULT_FADE = (1 << 22),
+ SEQ_USE_LINEAR_MODIFIERS = (1 << 23),
+
+ /* flags for whether those properties are animated or not */
+ SEQ_AUDIO_VOLUME_ANIMATED = (1 << 24),
+ SEQ_AUDIO_PITCH_ANIMATED = (1 << 25),
+ SEQ_AUDIO_PAN_ANIMATED = (1 << 26),
+ SEQ_AUDIO_DRAW_WAVEFORM = (1 << 27),
+
+ SEQ_INVALID_EFFECT = (1 << 31),
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison SEQ_MAKE_PREMUL
+#endif
/* convenience define for all selection flags */
#define SEQ_ALLSEL (SELECT + SEQ_LEFTSEL + SEQ_RIGHTSEL)
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index d01eceb44f0..25c98b4f07e 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -33,13 +33,19 @@
#define __DNA_SMOKE_TYPES_H__
/* flags */
-#define MOD_SMOKE_HIGHRES (1<<1) /* enable high resolution */
-#define MOD_SMOKE_DISSOLVE (1<<2) /* let smoke dissolve */
-#define MOD_SMOKE_DISSOLVE_LOG (1<<3) /* using 1/x for dissolve */
-
-#define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* -- Deprecated -- */
-#define MOD_SMOKE_FILE_LOAD (1<<6) /* flag for file load */
-#define MOD_SMOKE_ADAPTIVE_DOMAIN (1<<7)
+enum {
+ MOD_SMOKE_HIGHRES = (1 << 1), /* enable high resolution */
+ MOD_SMOKE_DISSOLVE = (1 << 2), /* let smoke dissolve */
+ MOD_SMOKE_DISSOLVE_LOG = (1 << 3), /* using 1/x for dissolve */
+
+ MOD_SMOKE_HIGH_SMOOTH = (1 << 5), /* -- Deprecated -- */
+ MOD_SMOKE_FILE_LOAD = (1 << 6), /* flag for file load */
+ MOD_SMOKE_ADAPTIVE_DOMAIN = (1 << 7),
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison MOD_SMOKE_HIGH_SMOOTH
+#endif
/* noise */
#define MOD_SMOKE_NOISEWAVE (1<<0)
diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h
index 040942d6cea..d7a51359777 100644
--- a/source/blender/makesdna/DNA_sound_types.h
+++ b/source/blender/makesdna/DNA_sound_types.h
@@ -33,6 +33,7 @@
#ifndef __DNA_SOUND_TYPES_H__
#define __DNA_SOUND_TYPES_H__
+#include "DNA_defs.h"
#include "DNA_ID.h"
/* stupid... could easily be solved */
@@ -109,14 +110,21 @@ typedef enum eSound_Type {
#endif
/* spacesound->flag */
-#define SND_DRAWFRAMES 1
-#define SND_CFRA_NUM 2
-
-#define SOUND_FLAGS_3D (1 << 3) /* deprecated! used for sound actuator loading */
-#define SOUND_FLAGS_CACHING (1 << 4)
-#define SOUND_FLAGS_MONO (1 << 5)
+enum {
+ SND_DRAWFRAMES = 1,
+ SND_CFRA_NUM = 2,
+};
+
+enum {
+ SOUND_FLAGS_3D = (1 << 3), /* deprecated! used for sound actuator loading */
+ SOUND_FLAGS_CACHING = (1 << 4),
+ SOUND_FLAGS_MONO = (1 << 5),
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison SOUND_FLAGS_3D
+#endif
/* to DNA_sound_types.h*/
#endif
-
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 4ebfe349a9f..4fe0920b7c6 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -455,10 +455,10 @@ typedef enum eScreen_Redraws_Flag {
TIME_ALL_3D_WIN = (1 << 1),
TIME_ALL_ANIM_WIN = (1 << 2),
TIME_ALL_BUTS_WIN = (1 << 3),
- TIME_WITH_SEQ_AUDIO = (1 << 4), /* DEPRECATED */
+ // TIME_WITH_SEQ_AUDIO = (1 << 4), /* DEPRECATED */
TIME_SEQ = (1 << 5),
TIME_ALL_IMAGE_WIN = (1 << 6),
- TIME_CONTINUE_PHYSICS = (1 << 7), /* UNUSED */
+ // TIME_CONTINUE_PHYSICS = (1 << 7), /* UNUSED */
TIME_NODES = (1 << 8),
TIME_CLIPS = (1 << 9),
} eScreen_Redraws_Flag;
@@ -969,7 +969,7 @@ typedef enum eSpaceNode_Flag {
SNODE_SHOW_B = (1 << 9),
SNODE_AUTO_RENDER = (1 << 5),
SNODE_SHOW_HIGHLIGHT = (1 << 6),
- SNODE_USE_HIDDEN_PREVIEW = (1 << 10),
+// SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013
SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
} eSpaceNode_Flag;
@@ -1179,6 +1179,11 @@ typedef enum eSpace_Type {
SPACEICONMAX = SPACE_CLIP
} eSpace_Type;
+// TODO: SPACE_SCRIPT
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison SPACE_IMASEL SPACE_SOUND
+#endif
+
#define IMG_SIZE_FALLBACK 256
#endif /* __DNA_SPACE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h
index ad9a2ea169c..4e6a762c36a 100644
--- a/source/blender/makesdna/DNA_tracking_types.h
+++ b/source/blender/makesdna/DNA_tracking_types.h
@@ -44,6 +44,7 @@
struct bGPdata;
struct ImBuf;
+struct Image;
struct MovieReconstructedCamera;
struct MovieTrackingCamera;
struct MovieTrackingBundle;
@@ -189,8 +190,11 @@ typedef struct MovieTrackingPlaneTrack {
int flag; /* flags (selection, ...) */
+ struct Image *image; /* Image displaying during editing */
+ float image_opacity; /* Opacity of the image */
+
/* Runtime data */
- int last_marker, pad2; /* Most recently used marker */
+ int last_marker; /* Most recently used marker */
} MovieTrackingPlaneTrack;
typedef struct MovieTrackingSettings {
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 37d5f313dfb..6aab0a0a0d1 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -257,10 +257,15 @@ typedef struct ThemeSpace {
char noodle_curving;
/* syntax for textwindow and nodes */
- char syntaxl[4], syntaxs[4];
- char syntaxb[4], syntaxn[4];
- char syntaxv[4], syntaxc[4];
- char syntaxd[4], syntaxr[4];
+ char syntaxl[4], syntaxs[4]; // in nodespace used for backdrop matte
+ char syntaxb[4], syntaxn[4]; // in nodespace used for color input
+ char syntaxv[4], syntaxc[4]; // in nodespace used for converter group
+ char syntaxd[4], syntaxr[4]; // in nodespace used for distort
+
+ char nodeclass_output[4], nodeclass_filter[4];
+ char nodeclass_vector[4], nodeclass_texture[4];
+ char nodeclass_shader[4], nodeclass_script[4];
+ char nodeclass_pattern[4], nodeclass_layout[4];
char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; /* for sequence editor */
char effect[4], transition[4], meta[4];
@@ -286,8 +291,8 @@ typedef struct ThemeSpace {
char preview_stitch_unstitchable[4];
char preview_stitch_active[4];
- char uv_shadow[4];
- char uv_others[4];
+ char uv_shadow[4]; /* two uses, for uvs with modifier applied on mesh and uvs during painting */
+ char uv_others[4]; /* uvs of other objects */
char match[4]; /* outliner - filter match */
char selected_highlight[4]; /* outliner - selected item */
@@ -374,6 +379,17 @@ typedef struct SolidLight {
float col[4], spec[4], vec[4];
} SolidLight;
+typedef struct WalkNavigation {
+ float mouse_speed; /* speed factor for look around */
+ float walk_speed;
+ float walk_speed_factor;
+ float view_height;
+ float jump_height;
+ float teleport_time; /* duration to use for teleporting */
+ short flag;
+ short pad[3];
+} WalkNavigation;
+
typedef struct UserDef {
/* UserDef has separate do-version handling, and can be read from other files */
int versionfile, subversionfile;
@@ -477,7 +493,7 @@ typedef struct UserDef {
float gpencil_new_layer_col[4]; /* default color for newly created Grease Pencil layers */
short tweak_threshold;
- short pad3;
+ char navigation_mode, pad;
char author[80]; /* author name for file formats supporting it */
@@ -486,6 +502,8 @@ typedef struct UserDef {
float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */
float pixelsize; /* private, set by GHOST, to multiply DPI with */
+
+ struct WalkNavigation walk_navigation;
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@@ -552,6 +570,18 @@ typedef enum eViewZoom_Style {
USER_ZOOM_DOLLY = 2
} eViewZoom_Style;
+/* navigation_mode */
+typedef enum eViewNavigation_Method {
+ VIEW_NAVIGATION_WALK = 0,
+ VIEW_NAVIGATION_FLY = 1,
+} eViewNavigation_Method;
+
+/* flag */
+typedef enum eWalkNavigation_Flag {
+ USER_WALK_GRAVITY = (1 << 0),
+ USER_WALK_MOUSE_REVERSE = (1 << 1),
+} eWalkNavigation_Flag;
+
/* uiflag */
typedef enum eUserpref_UI_Flag {
/* flags 0 and 1 were old flags (for autokeying) that aren't used anymore */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index c724340f5ea..a154f6fed15 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -266,6 +266,9 @@ typedef struct View3D {
#define RV3D_VIEW_PERSPORTHO 7
#define RV3D_VIEW_CAMERA 8
+#define RV3D_VIEW_IS_AXIS(view) \
+ ((view >= RV3D_VIEW_FRONT) && (view <= RV3D_VIEW_BOTTOM))
+
/* View3d->flag2 (short) */
#define V3D_RENDER_OVERRIDE 4
#define V3D_SOLID_TEX 8
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 3e01e159d6c..50542797f0b 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -142,7 +142,7 @@ typedef struct World {
/* mode */
#define WO_MIST 1
-#define WO_STARS 2 /* deprecated */
+//#define WO_STARS 2 /* deprecated */
/*#define WO_DOF 4*/
#define WO_ACTIVITY_CULLING 8
#define WO_ENV_LIGHT 16
@@ -151,10 +151,16 @@ typedef struct World {
#define WO_INDIRECT_LIGHT 128
/* aomix */
-#define WO_AOADD 0
-#define WO_AOSUB 1 /* deprecated */
-#define WO_AOADDSUB 2 /* deprecated */
-#define WO_AOMUL 3
+enum {
+ WO_AOADD = 0,
+ WO_AOSUB = 1, /* deprecated */
+ WO_AOADDSUB = 2, /* deprecated */
+ WO_AOMUL = 3,
+};
+
+#if (DNA_DEPRECATED_GCC_POISON == 1)
+#pragma GCC poison WO_AOSUB WO_AOADDSUB
+#endif
/* ao_samp_method - methods for sampling the AO hemi */
#define WO_AOSAMP_CONSTANT 0
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 2665da1b435..aac79245501 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -1209,6 +1209,14 @@ int main(int argc, char **argv)
#endif /* if 0 */
+/* even though DNA supports, 'long' shouldn't be used since it can be either 32 or 64bit,
+ * use int or int64_t instead.
+ * Only valid use would be as a runtime variable if an API expected a long,
+ * but so far we dont have this happening. */
+#ifdef __GNUC__
+# pragma GCC poison long
+#endif
+
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
#include "DNA_ID.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 14859852714..47824512379 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -296,6 +296,7 @@ extern StructRNA RNA_KinematicConstraint;
extern StructRNA RNA_Lamp;
extern StructRNA RNA_LampSkySettings;
extern StructRNA RNA_LampTextureSlot;
+extern StructRNA RNA_LaplacianDeformModifier;
extern StructRNA RNA_LaplacianSmoothModifier;
extern StructRNA RNA_LaplacianDeformModifier;
extern StructRNA RNA_Lattice;
@@ -493,6 +494,7 @@ extern StructRNA RNA_ShaderNodeExtendedMaterial;
extern StructRNA RNA_ShaderNodeGeometry;
extern StructRNA RNA_ShaderNodeHueSaturation;
extern StructRNA RNA_ShaderNodeInvert;
+extern StructRNA RNA_ShaderNodeLampData;
extern StructRNA RNA_ShaderNodeMapping;
extern StructRNA RNA_ShaderNodeMaterial;
extern StructRNA RNA_ShaderNodeMath;
@@ -640,6 +642,7 @@ extern StructRNA RNA_UserPreferencesFilePaths;
extern StructRNA RNA_UserPreferencesInput;
extern StructRNA RNA_UserPreferencesSystem;
extern StructRNA RNA_UserPreferencesView;
+extern StructRNA RNA_UserPreferencesWalkNavigation;
extern StructRNA RNA_UserSolidLight;
extern StructRNA RNA_VectorFont;
extern StructRNA RNA_VertexGroup;
@@ -1037,11 +1040,11 @@ char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *p
char *RNA_pointer_as_string_id(struct bContext *C, PointerRNA *ptr);
char *RNA_pointer_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop);
char *RNA_pointer_as_string_keywords_ex(struct bContext *C, PointerRNA *ptr,
- const bool skip_optional_value, const bool all_args,
+ const bool skip_optional_value, const bool all_args, const bool nested_args,
const int max_prop_length,
PropertyRNA *iterprop);
char *RNA_pointer_as_string_keywords(struct bContext *C, PointerRNA *ptr,
- const bool skip_optional_value, const bool all_args,
+ const bool skip_optional_value, const bool all_args, const bool nested_args,
const int max_prop_length);
char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func,
const bool as_function, const bool all_args,
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index f1881c8beba..34f5d1f3064 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -114,6 +114,7 @@ extern EnumPropertyItem rigidbody_object_shape_items[];
extern EnumPropertyItem rigidbody_constraint_type_items[];
extern EnumPropertyItem object_axis_items[];
+extern EnumPropertyItem object_axis_unsigned_items[];
extern EnumPropertyItem controller_type_items[];
@@ -135,6 +136,8 @@ extern EnumPropertyItem gameproperty_type_items[];
extern EnumPropertyItem viewport_shade_items[];
+extern EnumPropertyItem navigation_mode_items[];
+
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
int rna_node_tree_idname_to_enum(const char *idname);
struct bNodeTreeType *rna_node_tree_type_from_enum(int value);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 6c216936190..1811f2e1a5f 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -5040,7 +5040,7 @@ char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *p
/* context can be NULL */
char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr,
- const bool as_function, const bool all_args,
+ const bool as_function, const bool all_args, const bool nested_args,
const int max_prop_length,
PropertyRNA *iterprop)
{
@@ -5069,6 +5069,10 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr,
continue;
}
+ if ((nested_args == false) && (RNA_property_type(prop) == PROP_POINTER)) {
+ continue;
+ }
+
if (as_function && (flag & PROP_REQUIRED)) {
/* required args don't have useful defaults */
BLI_dynstr_appendf(dynstr, first_iter ? "%s" : ", %s", arg_name);
@@ -5113,14 +5117,14 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr,
}
char *RNA_pointer_as_string_keywords(bContext *C, PointerRNA *ptr,
- const bool as_function, const bool all_args,
+ const bool as_function, const bool all_args, const bool nested_args,
const int max_prop_length)
{
PropertyRNA *iterprop;
iterprop = RNA_struct_iterator_property(ptr->type);
- return RNA_pointer_as_string_keywords_ex(C, ptr, as_function, all_args,
+ return RNA_pointer_as_string_keywords_ex(C, ptr, as_function, all_args, nested_args,
max_prop_length, iterprop);
}
@@ -5137,7 +5141,7 @@ char *RNA_function_as_string_keywords(bContext *C, FunctionRNA *func,
RNA_struct_iterator_property(funcptr.type);
- return RNA_pointer_as_string_keywords_ex(C, &funcptr, as_function, all_args,
+ return RNA_pointer_as_string_keywords_ex(C, &funcptr, as_function, all_args, true,
max_prop_length, iterprop);
}
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index a07a000dacb..ce5049c1a6e 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -33,6 +33,7 @@
#include "DNA_scene_types.h" /* for MAXFRAME */
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BLF_translation.h"
@@ -1051,15 +1052,15 @@ static void rna_def_sound_actuator(BlenderRNA *brna)
"between this value and the normal gain in the inner cone)");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- prop = RNA_def_property(srna, "cone_outer_angle_3d", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "cone_outer_angle_3d", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "sound3D.cone_outer_angle");
- RNA_def_property_ui_range(prop, 0.0, 360.0, 1, 2);
+ RNA_def_property_ui_range(prop, 0.0, DEG2RADF(360.0f), 1, 2);
RNA_def_property_ui_text(prop, "Cone Outer Angle", "The angle of the outer cone");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- prop = RNA_def_property(srna, "cone_inner_angle_3d", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "cone_inner_angle_3d", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "sound3D.cone_inner_angle");
- RNA_def_property_ui_range(prop, 0.0, 360.0, 1, 2);
+ RNA_def_property_ui_range(prop, 0.0, DEG2RADF(360.0f), 1, 2);
RNA_def_property_ui_text(prop, "Cone Inner Angle", "The angle of the inner cone");
RNA_def_property_update(prop, NC_LOGIC, NULL);
@@ -1259,21 +1260,19 @@ static void rna_def_constraint_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Reference Direction", "Reference Direction");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- /*XXX TODO - use radians internally then change to PROP_ANGLE */
- prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "minloc[0]");
- RNA_def_property_range(prop, 0.0, 180.0);
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Min Angle",
- "Minimum angle (in degree) to maintain with target direction "
+ "Minimum angle to maintain with target direction "
"(no correction is done if angle with target direction is between min and max)");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- /*XXX TODO - use radians internally then change to PROP_ANGLE */
- prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "maxloc[0]");
- RNA_def_property_range(prop, 0.0, 180.0);
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Max Angle",
- "Maximum angle (in degree) allowed with target direction "
+ "Maximum angle allowed with target direction "
"(no correction is done if angle with target direction is between min and max)");
RNA_def_property_update(prop, NC_LOGIC, NULL);
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 405d38e9683..01e8c5956ff 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -131,7 +131,7 @@ static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
- !(br->flag & BRUSH_RESTORE_MESH) &&
+ !(br->flag & BRUSH_DRAG_DOT) &&
!ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
@@ -211,7 +211,7 @@ static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
- !(br->flag & BRUSH_RESTORE_MESH) &&
+ !(br->flag & BRUSH_DRAG_DOT) &&
!ELEM4(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
@@ -608,7 +608,7 @@ static void rna_def_brush(BlenderRNA *brna)
static EnumPropertyItem sculpt_stroke_method_items[] = {
{0, "DOTS", 0, "Dots", "Apply paint on each mouse move step"},
- {BRUSH_RESTORE_MESH, "DRAG_DOT", 0, "Drag Dot", "Allows a single dot to be carefully positioned"},
+ {BRUSH_DRAG_DOT, "DRAG_DOT", 0, "Drag Dot", "Allows a single dot to be carefully positioned"},
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_ANCHORED, "ANCHORED", 0, "Anchored", "Keep the brush anchored to the initial location"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
@@ -996,8 +996,8 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge-to-edge", "Drag anchor brush from edge-to-edge");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_restore_mesh", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RESTORE_MESH);
+ prop = RNA_def_property(srna, "use_drag_dot", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_DRAG_DOT);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 5743fcf2b9f..be973ab33f8 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -187,7 +187,8 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "lens");
- RNA_def_property_range(prop, 1.0f, 5000.0f);
+ RNA_def_property_range(prop, 1.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
@@ -235,7 +236,8 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "dof_distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "YF_dofdist");
- RNA_def_property_range(prop, 0.0f, 5000.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
RNA_def_property_ui_text(prop, "DOF Distance", "Distance to the focus point for depth of field");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index d848acd5971..c430a89655d 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -441,6 +441,11 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b
}
}
+static char *rna_ColorManagedDisplaySettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("display_settings");
+}
+
static int rna_ColorManagedViewSettings_view_transform_get(PointerRNA *ptr)
{
ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
@@ -521,6 +526,12 @@ static void rna_ColorManagedViewSettings_use_curves_set(PointerRNA *ptr, int val
}
}
+static char *rna_ColorManagedViewSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("view_settings");
+}
+
+
static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr)
{
ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data;
@@ -611,6 +622,16 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain)
}
}
+static char *rna_ColorManagedSequencerColorspaceSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("sequencer_colorspace_settings");
+}
+
+static char *rna_ColorManagedInputColorspaceSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("colorspace_settings");
+}
+
static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -1011,6 +1032,7 @@ static void rna_def_colormanage(BlenderRNA *brna)
/* ** Display Settings ** */
srna = RNA_def_struct(brna, "ColorManagedDisplaySettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_ColorManagedDisplaySettings_path");
RNA_def_struct_ui_text(srna, "ColorManagedDisplaySettings", "Color management specific to display device");
prop = RNA_def_property(srna, "display_device", PROP_ENUM, PROP_NONE);
@@ -1023,6 +1045,7 @@ static void rna_def_colormanage(BlenderRNA *brna)
/* ** View Settings ** */
srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_ColorManagedViewSettings_path");
RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display");
prop = RNA_def_property(srna, "look", PROP_ENUM, PROP_NONE);
@@ -1068,6 +1091,7 @@ static void rna_def_colormanage(BlenderRNA *brna)
/* ** Colorspace ** */
srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_ColorManagedInputColorspaceSettings_path");
RNA_def_struct_ui_text(srna, "ColorManagedInputColorspaceSettings", "Input color space settings");
prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
@@ -1079,7 +1103,9 @@ static void rna_def_colormanage(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
+ //
srna = RNA_def_struct(brna, "ColorManagedSequencerColorspaceSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_ColorManagedSequencerColorspaceSettings_path");
RNA_def_struct_ui_text(srna, "ColorManagedSequencerColorspaceSettings", "Input color space settings");
prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index fe9e9573957..fe38ce2d86a 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -66,11 +66,6 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
/* Duplicated code since we can't link in blenkernel or blenlib */
-#ifndef MIN2
-#define MIN2(x, y) ((x) < (y) ? (x) : (y))
-#define MAX2(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
/* pedantic check for '.', do this since its a hassle for translators */
#ifndef NDEBUG
# define DESCR_CHECK(description, id1, id2) \
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 9007baa9dad..8f4108c23d0 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -142,7 +142,6 @@ static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA
part->type = PART_FLUID;
psys->part = part;
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- psys->flag |= PSYS_ENABLED;
BLI_strncpy(psys->name, "FluidParticles", sizeof(psys->name));
BLI_addtail(&ob->particlesystem, psys);
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 210e0fef28f..7ddb172e2a2 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -618,7 +618,8 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_aspect", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "aspx");
RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, 0.1f, 5000.0f);
+ RNA_def_property_range(prop, 0.1f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.1f, 5000.f, 1, 2);
RNA_def_property_ui_text(prop, "Display Aspect", "Display Aspect for this image, does not affect rendering");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 7950ed424ee..807fad41373 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -239,6 +239,7 @@ void rna_TextureSlot_brush_update(struct Main *bmain, struct Scene *scene, struc
int rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Camera_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Curve_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
+int rna_Lamp_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Lattice_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
int rna_Mesh_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index 63fc5dbdbbd..2455141972b 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -156,19 +156,6 @@ static void rna_Lamp_sky_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
WM_main_add_notifier(NC_LAMP | ND_SKY, la);
}
-/* only for rad/deg conversion! can remove later */
-static float rna_Lamp_spot_size_get(PointerRNA *ptr)
-{
- Lamp *la = ptr->id.data;
- return DEG2RADF(la->spotsize);
-}
-
-static void rna_Lamp_spot_size_set(PointerRNA *ptr, float value)
-{
- Lamp *la = ptr->id.data;
- la->spotsize = RAD2DEGF(value);
-}
-
static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Lamp *la = (Lamp *)ptr->data;
@@ -800,11 +787,9 @@ static void rna_def_spot_lamp(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
prop = RNA_def_property(srna, "spot_size", PROP_FLOAT, PROP_ANGLE);
- /* RNA_def_property_float_sdna(prop, NULL, "spotsize"); */
- RNA_def_property_range(prop, M_PI / 180.0, M_PI);
+ RNA_def_property_float_sdna(prop, NULL, "spotsize");
+ RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(prop, "Spot Size", "Angle of the spotlight beam");
- /* only for deg/rad conversion */
- RNA_def_property_float_funcs(prop, "rna_Lamp_spot_size_get", "rna_Lamp_spot_size_set", NULL);
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
prop = RNA_def_property(srna, "show_cone", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 6c22a5cd5a4..c6f97e11156 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -743,34 +743,6 @@ static void rna_OceanModifier_ocean_chop_set(PointerRNA *ptr, float value)
}
}
-static float rna_EdgeSplitModifier_split_angle_get(PointerRNA *ptr)
-{
- EdgeSplitModifierData *md = (EdgeSplitModifierData *)ptr->data;
- return DEG2RADF(md->split_angle);
-}
-
-static void rna_EdgeSplitModifier_split_angle_set(PointerRNA *ptr, float value)
-{
- EdgeSplitModifierData *md = (EdgeSplitModifierData *)ptr->data;
- value = RAD2DEGF(value);
- CLAMP(value, 0.0f, 180.0f);
- md->split_angle = (int)value;
-}
-
-static float rna_BevelModifier_angle_limit_get(PointerRNA *ptr)
-{
- BevelModifierData *md = (BevelModifierData *)ptr->data;
- return DEG2RADF(md->bevel_angle);
-}
-
-static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value)
-{
- BevelModifierData *md = (BevelModifierData *)ptr->data;
- value = RAD2DEGF(value);
- CLAMP(value, 0.0f, 180.0f);
- md->bevel_angle = (int)value;
-}
-
static void rna_BevelModifier_defgrp_name_set(PointerRNA *ptr, const char *value)
{
BevelModifierData *md = (BevelModifierData *)ptr->data;
@@ -798,7 +770,7 @@ static void rna_LaplacianDeformModifier_vgroup_set(PointerRNA *ptr, const char *
static int rna_LaplacianDeformModifier_is_bind_get(PointerRNA *ptr)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)ptr->data;
- return ((lmd->flag & MOD_LAPLACIANDEFORM_BIND) && (lmd->cacheSystem != NULL));
+ return ((lmd->flag & MOD_LAPLACIANDEFORM_BIND) && (lmd->cache_system != NULL));
}
#else
@@ -1668,17 +1640,9 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "EdgeSplitModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT);
-#if 1 /* expose as radians */
prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_funcs(prop, "rna_EdgeSplitModifier_split_angle_get",
- "rna_EdgeSplitModifier_split_angle_set", NULL);
- RNA_def_property_range(prop, 0, DEG2RAD(180));
- RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2);
-#else
- prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0, 180);
- RNA_def_property_ui_range(prop, 0, 180, 100, 2);
-#endif
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 100, 2);
RNA_def_property_ui_text(prop, "Split Angle", "Angle above which to split edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2394,10 +2358,9 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_funcs(prop, "rna_BevelModifier_angle_limit_get",
- "rna_BevelModifier_angle_limit_set", NULL);
- RNA_def_property_range(prop, 0, DEG2RAD(180));
- RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2);
+ RNA_def_property_float_sdna(prop, NULL, "bevel_angle");
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 100, 2);
RNA_def_property_ui_text(prop, "Angle", "Angle above which to bevel edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2853,6 +2816,16 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "use_stretch_u", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_UV_STRETCH_U);
+ RNA_def_property_ui_text(prop, "Stretch U", "Stretch the U coordinates between 0-1 when UV's are present");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_stretch_v", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_UV_STRETCH_V);
+ RNA_def_property_ui_text(prop, "Stretch V", "Stretch the V coordinates between 0-1 when UV's are present");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
#if 0
prop = RNA_def_property(srna, "use_angle_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SCREW_OBJECT_ANGLE);
@@ -3700,12 +3673,12 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "LaplacianDeformModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Laplacian Deform Modifier", "Mesh deform modifier");
RNA_def_struct_sdna(srna, "LaplacianDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
-
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "anchor_grp_name");
RNA_def_property_ui_text(prop, "Vertex Group for Anchors",
@@ -3720,7 +3693,7 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
prop = RNA_def_property(srna, "is_bind", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_LaplacianDeformModifier_is_bind_get", NULL);
- RNA_def_property_ui_text(prop, "Bind", "Whether geometry has been bind to anchors");
+ RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to anchors");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index e7a967084f3..170856a3061 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -295,7 +295,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_aspect", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "aspx");
RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, 0.1f, 5000.0f);
+ RNA_def_property_range(prop, 0.1f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.1f, 5000.0f, 1, 2);
RNA_def_property_ui_text(prop, "Display Aspect", "Display Aspect for this clip, does not affect rendering");
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 6b5bced75bd..55989bd985c 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -793,6 +793,11 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
nodeFindNode(ntree, fromsock, &fromnode, NULL);
nodeFindNode(ntree, tosock, &tonode, NULL);
+ /* check validity of the sockets:
+ * if sockets from different trees are passed in this will fail!
+ */
+ if (!fromnode || !tonode)
+ return NULL;
if (&fromsock->in_out == &tosock->in_out) {
BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
@@ -3258,6 +3263,19 @@ static void def_sh_geometry(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_sh_lamp(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "lamp_object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Lamp_object_poll");
+ RNA_def_property_ui_text(prop, "Lamp Object", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_sh_attribute(StructRNA *srna)
{
PropertyRNA *prop;
@@ -4833,7 +4851,6 @@ static void def_cmp_defocus(StructRNA *srna)
RNA_def_property_ui_text(prop, "Bokeh Type", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- /* TODO: angle in degrees */
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "rotation");
RNA_def_property_range(prop, 0.0f, DEG2RADF(90.0f));
@@ -5439,7 +5456,7 @@ static void def_cmp_mask(StructRNA *srna)
prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_MASK_MOTION_BLUR);
- RNA_def_property_ui_text(prop, "Motion Blur", "Use feather information from the mask");
+ RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled motion blur of the mask");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_NONE);
@@ -5536,10 +5553,10 @@ static void def_cmp_boxmask(StructRNA *srna)
RNA_def_property_ui_text(prop, "Height", "Height of the box");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "rotation");
RNA_def_property_float_default(prop, 0.0f);
- RNA_def_property_range(prop, -1000.0f, 1000.0f);
+ RNA_def_property_range(prop, DEG2RADF(-1800.0f), DEG2RADF(1800.0f));
RNA_def_property_ui_text(prop, "Rotation", "Rotation angle of the box");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
@@ -5559,35 +5576,35 @@ static void def_cmp_ellipsemask(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "x");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -1.0f, 2.0f);
- RNA_def_property_ui_text(prop, "X", "X position of the middle of the box");
+ RNA_def_property_ui_text(prop, "X", "X position of the middle of the ellipse");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "y");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -1.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Y", "Y position of the middle of the box");
+ RNA_def_property_ui_text(prop, "Y", "Y position of the middle of the ellipse");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "width");
RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_range(prop, 0.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Width", "Width of the box");
+ RNA_def_property_ui_text(prop, "Width", "Width of the ellipse");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "height");
RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_range(prop, 0.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Height", "Height of the box");
+ RNA_def_property_ui_text(prop, "Height", "Height of the ellipse");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "rotation");
RNA_def_property_float_default(prop, 0.0f);
- RNA_def_property_range(prop, -1000.0f, 1000.0f);
- RNA_def_property_ui_text(prop, "Rotation", "Rotation angle of the box");
+ RNA_def_property_range(prop, DEG2RADF(-1800.0f), DEG2RADF(1800.0f));
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation angle of the ellipse");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
@@ -5626,10 +5643,10 @@ static void def_cmp_bokehimage(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeBokehImage", "storage");
- prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "angle");
RNA_def_property_float_default(prop, 0.0f);
- RNA_def_property_range(prop, -720.0f, 720.0f);
+ RNA_def_property_range(prop, DEG2RADF(-720.0f), DEG2RADF(720.0f));
RNA_def_property_ui_text(prop, "Angle", "Angle of the bokeh");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 3f366dfbcfa..9c1d0c4cc2b 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -165,6 +165,14 @@ EnumPropertyItem object_axis_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/* for general use (not just object) */
+EnumPropertyItem object_axis_unsigned_items[] = {
+ {0, "X", 0, "X", ""},
+ {1, "Y", 0, "Y", ""},
+ {2, "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "BLI_math.h"
@@ -1446,6 +1454,11 @@ int rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
return ((Object *)value.id.data)->type == OB_CAMERA;
}
+int rna_Lamp_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
+{
+ return ((Object *)value.id.data)->type == OB_LAMP;
+}
+
int rna_DupliObject_index_get(PointerRNA *ptr)
{
DupliObject *dob = (DupliObject *)ptr->data;
@@ -1633,6 +1646,10 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Physics Type", "Select the type of physical representation");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop = RNA_def_property(srna, "use_record_animation", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_RECORD_ANIMATION);
+ RNA_def_property_ui_text(prop, "Record Animation", "Record animation objects without physics");
+
prop = RNA_def_property(srna, "use_actor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gameflag", OB_ACTOR);
RNA_def_property_ui_text(prop, "Actor", "Object is detected by the Near and Radar sensor");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 2a93925a8e5..b8cf7a13b74 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -523,6 +523,18 @@ static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA
}
}
+static void rna_FieldSettings_type_set(PointerRNA *ptr, int value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ ob->pd->forcefield = value;
+ if (ELEM(value, PFIELD_WIND, PFIELD_VORTEX)) {
+ ob->empty_drawtype = OB_SINGLE_ARROW;
+ }
+ else {
+ ob->empty_drawtype = OB_PLAINAXES;
+ }
+}
+
static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
if (particle_id_check(ptr)) {
@@ -1159,6 +1171,7 @@ static void rna_def_field(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "forcefield");
RNA_def_property_enum_items(prop, field_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_FieldSettings_type_set", NULL);
RNA_def_property_ui_text(prop, "Type", "Type of field");
RNA_def_property_update(prop, 0, "rna_FieldSettings_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 5151310cd64..01e7b673838 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -136,6 +136,7 @@ static EnumPropertyItem part_hair_ren_as_items[] = {
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
+#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -390,6 +391,47 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
}
+
+static EnumPropertyItem *rna_Particule_Material_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *ob = CTX_data_active_object(C);
+ Material *ma;
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0;
+ int i;
+
+ if (ob->totcol > 0) {
+ for (i = 1; i <= ob->totcol; i++) {
+ ma = give_current_material(ob, i);
+ tmp.value = i;
+ tmp.icon = ICON_MATERIAL_DATA;
+ if (ma) {
+ tmp.name = ma->id.name + 2;
+ tmp.identifier = tmp.name;
+ }
+ else {
+ tmp.name = "Default Material";
+ tmp.identifier = tmp.name;
+ }
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+ }
+ else {
+ tmp.value = 1;
+ tmp.icon = ICON_MATERIAL_DATA;
+ tmp.name = "Default Material";
+ tmp.identifier = tmp.name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
ParticleSystemModifierData *modifier, ParticleData *particle,
int particle_no, int uv_no,
@@ -2018,6 +2060,11 @@ static void rna_def_particle_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem part_mat_items[] = {
+ {0, "DUMMY", 0, "Dummy", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "ParticleSettings", "ID");
RNA_def_struct_ui_text(srna, "Particle Settings", "Particle settings, reusable by multiple particle systems");
RNA_def_struct_ui_icon(srna, ICON_PARTICLE_DATA);
@@ -2360,7 +2407,14 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "material", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "omat");
RNA_def_property_range(prop, 1, 32767);
- RNA_def_property_ui_text(prop, "Material", "Material used for the particles");
+ RNA_def_property_ui_text(prop, "Material Index", "Index of material slot used for rendering particles");
+ RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
+ prop = RNA_def_property(srna, "material_slot", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "omat");
+ RNA_def_property_enum_items(prop, part_mat_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particule_Material_itemf");
+ RNA_def_property_ui_text(prop, "Material Slot", "Material slot used for rendering particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "integrator", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 686672e1629..0daa8c97dec 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2655,27 +2655,6 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem freestyle_raycasting_algorithm_items[] = {
- {FREESTYLE_ALGO_REGULAR, "REGULAR", 0, "Normal Ray Casting", "Consider all FEdges in each ViewEdge"},
- {FREESTYLE_ALGO_FAST, "FAST", 0, "Fast Ray Casting", "Sample some FEdges in each ViewEdge"},
- {FREESTYLE_ALGO_VERYFAST, "VERYFAST", 0, "Very Fast Ray Casting",
- "Sample one FEdge in each ViewEdge; do not save list of occluders"},
- {FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL, "CULLEDADAPTIVETRADITIONAL", 0,
- "Culled Traditional Visibility Detection",
- "Culled adaptive grid with heuristic density and "
- "traditional QI calculation"},
- {FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL, "ADAPTIVETRADITIONAL", 0, "Unculled Traditional Visibility Detection",
- "Adaptive grid with heuristic density and traditional QI calculation"},
- {FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE, "CULLEDADAPTIVECUMULATIVE", 0,
- "Culled Cumulative Visibility Detection",
- "Culled adaptive grid with heuristic density and "
- "cumulative QI calculation"},
- {FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE, "ADAPTIVECUMULATIVE", 0, "Unculled Cumulative Visibility Detection",
- "Adaptive grid with heuristic density and cumulative QI calculation"},
- {0, NULL, 0, NULL, NULL}
- };
-
-
/* FreestyleLineSet */
srna = RNA_def_struct(brna, "FreestyleLineSet", NULL);
@@ -2922,12 +2901,6 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "raycasting_algorithm", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "raycasting_algorithm");
- RNA_def_property_enum_items(prop, freestyle_raycasting_algorithm_items);
- RNA_def_property_ui_text(prop, "Raycasting Algorithm", "Select the Freestyle raycasting algorithm");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "use_culling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_CULLING);
RNA_def_property_ui_text(prop, "Culling", "If enabled, out-of-view edges are ignored");
@@ -3665,7 +3638,9 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "compression", PROP_INT, PROP_PERCENTAGE);
RNA_def_property_int_sdna(prop, NULL, "compress");
RNA_def_property_range(prop, 0, 100); /* 0 is needed for compression. */
- RNA_def_property_ui_text(prop, "Compression", "Compression level for formats that support lossless compression");
+ RNA_def_property_ui_text(prop, "Compression", "Amount of time to determine best compression: "
+ "0 = no compression with fast file output, "
+ "100 = maximum lossless compression with slow file output");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* flag */
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index a9f84f1dcc7..6280e0833e5 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -305,23 +305,58 @@ static void rna_def_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_brush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH);
RNA_def_property_ui_text(prop, "Show Brush", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "show_brush_on_surface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH_ON_SURFACE);
RNA_def_property_ui_text(prop, "Show Brush On Surface", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "show_low_resolution", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_FAST_NAVIGATE);
RNA_def_property_ui_text(prop, "Fast Navigate", "For multires, show low resolution while navigating the view");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "num_input_samples");
RNA_def_property_ui_range(prop, 1, PAINT_MAX_INPUT_SAMPLES, 0, -1);
RNA_def_property_ui_text(prop, "Input Samples", "Average multiple input samples together to smooth the brush stroke");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "use_symmetry_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_SYMM_X);
+ RNA_def_property_ui_text(prop, "Symmetry X", "Mirror brush across the X axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "use_symmetry_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_SYMM_Y);
+ RNA_def_property_ui_text(prop, "Symmetry Y", "Mirror brush across the Y axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "use_symmetry_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_SYMM_Z);
+ RNA_def_property_ui_text(prop, "Symmetry Z", "Mirror brush across the Z axis");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "use_symmetry_feather", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "symmetry_flags", PAINT_SYMMETRY_FEATHER);
+ RNA_def_property_ui_text(prop, "Symmetry Feathering",
+ "Reduce the strength of the brush where it overlaps symmetrical daubs");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
static void rna_def_sculpt(BlenderRNA *brna)
{
+ static EnumPropertyItem detail_refine_items[] = {
+ {SCULPT_DYNTOPO_SUBDIVIDE, "SUBDIVIDE", 0,
+ "Subdivide Edges", "Subdivide long edges to add mesh detail where needed"},
+ {SCULPT_DYNTOPO_COLLAPSE, "COLLAPSE", 0,
+ "Collapse Edges", "Collapse short edges to remove mesh detail where possible"},
+ {SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE, "SUBDIVIDE_COLLAPSE", 0,
+ "Subdivide Collapse", "Both subdivide long edges and collapse short edges to refine mesh detail"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
StructRNA *srna;
PropertyRNA *prop;
@@ -337,21 +372,6 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Radial Symmetry Count X Axis",
"Number of times to copy strokes across the surface");
- prop = RNA_def_property(srna, "use_symmetry_x", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMM_X);
- RNA_def_property_ui_text(prop, "Symmetry X", "Mirror brush across the X axis");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- prop = RNA_def_property(srna, "use_symmetry_y", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMM_Y);
- RNA_def_property_ui_text(prop, "Symmetry Y", "Mirror brush across the Y axis");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- prop = RNA_def_property(srna, "use_symmetry_z", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMM_Z);
- RNA_def_property_ui_text(prop, "Symmetry Z", "Mirror brush across the Z axis");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
prop = RNA_def_property(srna, "lock_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_LOCK_X);
RNA_def_property_ui_text(prop, "Lock X", "Disallow changes to the X axis of vertices");
@@ -367,12 +387,6 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Lock Z", "Disallow changes to the Z axis of vertices");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
- prop = RNA_def_property(srna, "use_symmetry_feather", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMMETRY_FEATHER);
- RNA_def_property_ui_text(prop, "Symmetry Feathering",
- "Reduce the strength of the brush where it overlaps symmetrical daubs");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
prop = RNA_def_property(srna, "use_threaded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_USE_OPENMP);
RNA_def_property_ui_text(prop, "Use OpenMP",
@@ -403,16 +417,16 @@ static void rna_def_sculpt(BlenderRNA *brna)
"shading rather than flat shaded");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
- prop = RNA_def_property(srna, "use_edge_collapse", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_COLLAPSE);
- RNA_def_property_ui_text(prop, "Collapse Short Edges",
- "In dynamic-topology mode, collapse short edges "
- "in addition to subdividing long ones");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, symmetrize_direction_items);
RNA_def_property_ui_text(prop, "Direction", "Source and destination for symmetrize operator");
+
+ prop = RNA_def_property(srna, "detail_refine_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, detail_refine_items);
+ RNA_def_property_ui_text(prop, "Detail Refine Method",
+ "In dynamic-topology mode, how to add or remove mesh detail");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 71546c7fad4..4458cac3e3d 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -31,6 +31,7 @@
#include "DNA_sensor_types.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BLF_translation.h"
@@ -663,10 +664,9 @@ static void rna_def_radar_sensor(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Axis", "Along which axis the radar cone is cast");
RNA_def_property_update(prop, NC_LOGIC, NULL);
- /*XXX TODO - use radians internally then change to PROP_ANGLE */
- prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 179.9);
- RNA_def_property_ui_text(prop, "Angle", "Opening angle of the radar cone (in degrees)");
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_range(prop, 0.0, DEG2RADF(179.9f));
+ RNA_def_property_ui_text(prop, "Angle", "Opening angle of the radar cone");
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 342d94c7667..a73a7f41d7e 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -884,22 +884,6 @@ static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value)
ed->over_ofs = value;
}
-
-static void rna_WipeSequence_angle_set(PointerRNA *ptr, float value)
-{
- Sequence *seq = (Sequence *)(ptr->data);
- value = RAD2DEGF(value);
- CLAMP(value, -90.0f, 90.0f);
- ((WipeVars *)seq->effectdata)->angle = value;
-}
-
-static float rna_WipeSequence_angle_get(PointerRNA *ptr)
-{
- Sequence *seq = (Sequence *)(ptr->data);
-
- return DEG2RADF(((WipeVars *)seq->effectdata)->angle);
-}
-
static int modifier_seq_cmp_cb(Sequence *seq, void *arg_pt)
{
SequenceSearchData *data = arg_pt;
@@ -2042,18 +2026,11 @@ static void rna_def_wipe(StructRNA *srna)
"Width of the blur edge, in percentage relative to the image size");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
-#if 1 /* expose as radians */
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_funcs(prop, "rna_WipeSequence_angle_get", "rna_WipeSequence_angle_set", NULL);
- RNA_def_property_range(prop, DEG2RAD(-90.0), DEG2RAD(90.0));
-#else
- prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "angle");
- RNA_def_property_range(prop, -90.0f, 90.0f);
-#endif
+ RNA_def_property_range(prop, DEG2RADF(-90.0f), DEG2RADF(90.0f));
RNA_def_property_ui_text(prop, "Angle", "Edge angle");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
-
+
prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "forward");
RNA_def_property_enum_items(prop, wipe_direction_items);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 6545661cdf1..fdaf204be23 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -100,12 +100,12 @@ static EnumPropertyItem draw_channels_items[] = {
static EnumPropertyItem transform_orientation_items[] = {
{V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", "Align the transformation axes to world space"},
{V3D_MANIP_LOCAL, "LOCAL", 0, "Local", "Align the transformation axes to the selected objects' local space"},
- {V3D_MANIP_GIMBAL, "GIMBAL", 0, "Gimbal", "Align each axis to the Euler rotation axis as used for input"},
{V3D_MANIP_NORMAL, "NORMAL", 0, "Normal",
"Align the transformation axes to average normal of selected elements "
"(bone Y axis for pose mode)"},
+ {V3D_MANIP_GIMBAL, "GIMBAL", 0, "Gimbal", "Align each axis to the Euler rotation axis as used for input"},
{V3D_MANIP_VIEW, "VIEW", 0, "View", "Align the transformation axes to the window"},
- {V3D_MANIP_CUSTOM, "CUSTOM", 0, "Custom", "Use a custom transform orientation"},
+ // {V3D_MANIP_CUSTOM, "CUSTOM", 0, "Custom", "Use a custom transform orientation"},
{0, NULL, 0, NULL, NULL}
};
@@ -291,7 +291,7 @@ static PointerRNA rna_CurrentOrientation_get(PointerRNA *ptr)
{
Scene *scene = ((bScreen *)ptr->id.data)->scene;
View3D *v3d = (View3D *)ptr->data;
-
+
if (v3d->twmode < V3D_MANIP_CUSTOM)
return rna_pointer_inherit_refine(ptr, &RNA_TransformOrientation, NULL);
else
@@ -308,11 +308,7 @@ EnumPropertyItem *rna_TransformOrientation_itemf(bContext *C, PointerRNA *ptr, P
EnumPropertyItem *item = NULL;
int i = V3D_MANIP_CUSTOM, totitem = 0;
- RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_GLOBAL);
- RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_LOCAL);
- RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_NORMAL);
- RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_GIMBAL);
- RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_VIEW);
+ RNA_enum_items_add(&item, &totitem, transform_orientation_items);
if (ptr->type == &RNA_SpaceView3D)
scene = ((bScreen *)ptr->id.data)->scene;
@@ -1851,9 +1847,9 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_UNIT_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "lens");
- RNA_def_property_ui_text(prop, "Lens", "Viewport lens angle (mm)");
+ RNA_def_property_ui_text(prop, "Lens", "Viewport lens angle");
RNA_def_property_range(prop, 1.0f, 250.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -3485,11 +3481,6 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Highlight", "Highlight nodes that are being calculated");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
- prop = RNA_def_property(srna, "use_hidden_preview", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_USE_HIDDEN_PREVIEW);
- RNA_def_property_ui_text(prop, "Hide Preview", "Hide preview for newly creating nodes");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
-
/* the mx/my "cursor" in the node editor is used only by operators to store the mouse position */
prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(prop, 2);
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index a0aed94f3c6..871bc159f28 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -962,7 +962,8 @@ static void rna_def_trackingCamera(BlenderRNA *brna)
prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "focal");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.0001f, 5000.0f);
+ RNA_def_property_range(prop, 0.0001f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0001f, 5000.0f, 1, 2);
RNA_def_property_float_funcs(prop, "rna_trackingCamera_focal_mm_get", "rna_trackingCamera_focal_mm_set", NULL);
RNA_def_property_ui_text(prop, "Focal Length", "Camera's focal length");
RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
@@ -971,7 +972,8 @@ static void rna_def_trackingCamera(BlenderRNA *brna)
prop = RNA_def_property(srna, "focal_length_pixels", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "focal");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.0f, 5000.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 5000.f, 1, 2);
RNA_def_property_ui_text(prop, "Focal Length", "Camera's focal length");
RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
@@ -1017,7 +1019,7 @@ static void rna_def_trackingCamera(BlenderRNA *brna)
prop = RNA_def_property(srna, "pixel_aspect", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "pixel_aspect");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0.1f, 5000.0f);
+ RNA_def_property_range(prop, 0.1f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.1f, 5000.0f, 1, 2);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Pixel Aspect Ratio", "Pixel aspect ratio");
@@ -1472,6 +1474,20 @@ static void rna_def_trackingPlaneTrack(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_TRACK_AUTOKEY);
RNA_def_property_ui_text(prop, "Auto Keyframe", "Automatic keyframe insertion when moving plane corners");
RNA_def_property_ui_icon(prop, ICON_REC, 0);
+
+ /* image */
+ prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Image", "Image displayed in the track during editing in clip editor");
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+
+ /* image opacity */
+ prop = RNA_def_property(srna, "image_opacity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Image Opacity", "Opacity of the image");
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
}
static void rna_def_trackingStabilization(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index d79a40aa615..dcf51cdceaf 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -97,7 +97,7 @@ static const char *rna_translate_ui_text(const char *text, const char *text_ctxt
static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt,
int translate, int icon, int expand, int slider, int toggle, int icon_only, int event,
- int full_event, int emboss, int index)
+ int full_event, int emboss, int index, int icon_value)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
int flag = 0;
@@ -107,6 +107,10 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname,
return;
}
+ if (icon_value && !icon) {
+ icon = icon_value;
+ }
+
/* Get translated name (label). */
name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
@@ -511,6 +515,10 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_int(func, "index", -1, -2, INT_MAX, "",
"The index of this button, when set a single member of an array can be accessed, "
"when set to -1 all array members are used", -2, INT_MAX); /* RNA_NO_INDEX == -1 */
+ parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(parm, "Icon Value",
+ "Override automatic icon of the item "
+ "(use it e.g. with custom material icons returned by icon()...)");
func = RNA_def_function(srna, "props_enum", "uiItemsEnumR");
api_ui_item_rna_common(func);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 0e45d6d4aea..f138964f8e3 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -72,6 +72,12 @@ static EnumPropertyItem audio_device_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem navigation_mode_items[] = {
+ {VIEW_NAVIGATION_WALK, "WALK", 0, "Walk", "Interactively walk or free navigate around the scene"},
+ {VIEW_NAVIGATION_FLY, "FLY", 0, "Fly", "Use fly dynamics to navigate the scene"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_object_types.h"
@@ -1958,22 +1964,16 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Node Backdrop", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "in_out_node", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "syntaxn");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "In/Out Node", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "converter_node", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "syntaxv");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Converter Node", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "operator_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "color_node", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "syntaxb");
RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Operator Node", "");
+ RNA_def_property_ui_text(prop, "Color Node", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "group_node", PROP_FLOAT, PROP_COLOR_GAMMA);
@@ -2012,6 +2012,60 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 10);
RNA_def_property_ui_text(prop, "Noodle curving", "Curving of the noodle");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "input_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxn");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Input Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "output_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_output");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Output Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "filter_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_filter");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Filter Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "vector_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_vector");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Vector Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "texture_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_texture");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Texture Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "shader_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_shader");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Shader Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "script_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_script");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Script Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "pattern_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_pattern");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Pattern Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "layout_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "nodeclass_layout");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Layout Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_logic(BlenderRNA *brna)
@@ -2093,7 +2147,17 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Active Vert/Edge/Face", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
-
+
+ prop = RNA_def_property(srna, "wire_edit", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Wire Edit", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "edge_select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Edge Select", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "scope_back", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_back");
RNA_def_property_array(prop, 4);
@@ -2873,6 +2937,51 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
}
+static void rna_def_userdef_walk_navigation(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "WalkNavigation", NULL);
+ RNA_def_struct_sdna(srna, "WalkNavigation");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Walk Navigation", "Walk navigation settings");
+
+ prop = RNA_def_property(srna, "mouse_speed", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.01f, 10.0f);
+ RNA_def_property_ui_text(prop, "Mouse Sensitivity", "Speed factor for when looking around, high values mean faster mouse movement");
+
+ prop = RNA_def_property(srna, "walk_speed", PROP_FLOAT, PROP_VELOCITY);
+ RNA_def_property_range(prop, 0.01f, 100.f);
+ RNA_def_property_ui_text(prop, "Walk Speed", "Base speed for walking and flying");
+
+ prop = RNA_def_property(srna, "walk_speed_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.01f, 10.f);
+ RNA_def_property_ui_text(prop, "Speed Factor", "Multiplication factor when using the fast or slow modifiers");
+
+ prop = RNA_def_property(srna, "view_height", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_ui_range(prop, 0.1f, 10.f, 0.1, 2);
+ RNA_def_property_range(prop, 0.f, 1000.f);
+ RNA_def_property_ui_text(prop, "View Height", "View distance from the floor when walking");
+
+ prop = RNA_def_property(srna, "jump_height", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_ui_range(prop, 0.1f, 10.f, 0.1, 2);
+ RNA_def_property_range(prop, 0.1f, 100.f);
+ RNA_def_property_ui_text(prop, "Jump Height", "Maximum height of a jump");
+
+ prop = RNA_def_property(srna, "teleport_time", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.f, 10.f);
+ RNA_def_property_ui_text(prop, "Teleport Duration", "Interval of time warp when teleporting in navigation mode");
+
+ prop = RNA_def_property(srna, "use_gravity", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_WALK_GRAVITY);
+ RNA_def_property_ui_text(prop, "Gravity", "Walk with gravity, or free navigate");
+
+ prop = RNA_def_property(srna, "use_mouse_reverse", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_WALK_MOUSE_REVERSE);
+ RNA_def_property_ui_text(prop, "Reverse Mouse", "Reverse the mouse look");
+}
+
static void rna_def_userdef_view(BlenderRNA *brna)
{
static EnumPropertyItem timecode_styles[] = {
@@ -3793,7 +3902,19 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Continuous Grab",
"Allow moving the mouse outside the view on some manipulations "
"(transform, ui control drag)");
-
+
+ /* View Navigation */
+ prop = RNA_def_property(srna, "navigation_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "navigation_mode");
+ RNA_def_property_enum_items(prop, navigation_mode_items);
+ RNA_def_property_ui_text(prop, "View Navigation", "Which method to use for viewport navigation");
+
+ prop = RNA_def_property(srna, "walk_navigation", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "walk_navigation");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "WalkNavigation");
+ RNA_def_property_ui_text(prop, "Walk Navigation", "Settings for walk navigation mode");
+
/* tweak tablet & mouse preset */
prop = RNA_def_property(srna, "drag_threshold", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dragthreshold");
@@ -4128,6 +4249,7 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_dothemes(brna);
rna_def_userdef_solidlight(brna);
+ rna_def_userdef_walk_navigation(brna);
srna = RNA_def_struct(brna, "UserPreferences", NULL);
RNA_def_struct_sdna(srna, "UserDef");
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 09451599ce5..fd477f1106e 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -319,7 +319,7 @@ EnumPropertyItem event_type_items[] = {
{TIMERJOBS, "TIMER_JOBS", 0, "Timer Jobs", ""},
{TIMERAUTOSAVE, "TIMER_AUTOSAVE", 0, "Timer Autosave", ""},
{TIMERREPORT, "TIMER_REPORT", 0, "Timer Report", ""},
- {TIMERREGION, "TIMER_REGION", 0, "Timer Region", ""},
+ {TIMERREGION, "TIMERREGION", 0, "Timer Region", ""},
{0, "", 0, NULL, NULL},
{NDOF_MOTION, "NDOF_MOTION", 0, "NDOF Motion", ""},
/* buttons on all 3dconnexion devices */
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 91cddd28be0..923e7f98360 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -135,16 +135,22 @@ static void rna_progress_update(struct wmWindowManager *wm, float value)
{
if (wm_progress_state.is_valid) {
/* Map to cursor_time range [0,9999] */
- int val = (int)(10000 * (value - wm_progress_state.min) / (wm_progress_state.max - wm_progress_state.min));
- WM_cursor_time(wm->winactive, val);
+ wmWindow *win = wm->winactive;
+ if (win) {
+ int val = (int)(10000 * (value - wm_progress_state.min) / (wm_progress_state.max - wm_progress_state.min));
+ WM_cursor_time(win, val);
+ }
}
}
static void rna_progress_end(struct wmWindowManager *wm)
{
if (wm_progress_state.is_valid) {
- WM_cursor_modal_restore(wm->winactive);
- wm_progress_state.is_valid = false;
+ wmWindow *win = wm->winactive;
+ if (win) {
+ WM_cursor_modal_restore(win);
+ wm_progress_state.is_valid = false;
+ }
}
}
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 450501c9db5..4eb15c0fbdb 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -36,7 +36,6 @@ set(INC
../render/extern/include
../../../intern/elbeem/extern
../../../intern/guardedalloc
- ../../../intern/opennl/extern
)
set(INC_SYS
@@ -146,4 +145,11 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_OPENNL)
+ add_definitions(-DWITH_OPENNL)
+ list(APPEND INC_SYS
+ ../../../intern/opennl/extern
+ )
+endif()
+
blender_add_lib(bf_modifiers "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 6a1de92f9b2..3ba06a73c8b 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -61,7 +61,7 @@ static void initData(ModifierData *md)
bmd->val_flags = 0;
bmd->lim_flags = 0;
bmd->e_flags = 0;
- bmd->bevel_angle = 30;
+ bmd->bevel_angle = DEG2RADF(30.0f);
bmd->defgrp_name[0] = '\0';
}
@@ -107,7 +107,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
int vgroup = -1;
MDeformVert *dvert = NULL;
BevelModifierData *bmd = (BevelModifierData *) md;
- const float threshold = cosf((bmd->bevel_angle + 0.00001f) * (float)M_PI / 180.0f);
+ const float threshold = cosf(bmd->bevel_angle + 0.000000175f);
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK);
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index d55ebdad939..a17858d58f5 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -55,7 +55,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd)
BMesh *bm;
BMIter iter;
BMEdge *e;
- float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f);
+ float threshold = cosf(emd->split_angle + 0.000000175f);
const bool calc_face_normals = (emd->flags & MOD_EDGESPLIT_FROMANGLE) != 0;
bm = DM_to_bmesh(dm, calc_face_normals);
@@ -107,7 +107,7 @@ static void initData(ModifierData *md)
EdgeSplitModifierData *emd = (EdgeSplitModifierData *) md;
/* default to 30-degree split angle, sharpness from both angle & flag */
- emd->split_angle = 30;
+ emd->split_angle = DEG2RADF(30.0f);
emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 0471539dc14..df64bf63ff7 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
+ * The Original Code is Copyright (C) 2013 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s): Alexander Pinzon Fernandez
@@ -23,7 +23,7 @@
* ***** END GPL LICENSE BLOCK *****
*
*/
-
+
/** \file blender/modifiers/intern/MOD_laplaciandeform.c
* \ingroup modifiers
*/
@@ -41,16 +41,21 @@
#include "MOD_util.h"
-#include "ONL_opennl.h"
-#define LAPDEFORM_SYSTEM_NOT_CHANGE 0
-#define LAPDEFORM_SYSTEM_IS_DIFFERENT 1
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS 2
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP 3
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_MESH 4
-#define LAPDEFORM_SYSTEM_CHANGE_VERTEXES 5
-#define LAPDEFORM_SYSTEM_CHANGE_EDGES 6
-#define LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP 7
+enum {
+ LAPDEFORM_SYSTEM_NOT_CHANGE = 0,
+ LAPDEFORM_SYSTEM_IS_DIFFERENT,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_MESH,
+ LAPDEFORM_SYSTEM_CHANGE_VERTEXES,
+ LAPDEFORM_SYSTEM_CHANGE_EDGES,
+ LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP,
+};
+
+#ifdef WITH_OPENNL
+
+#include "ONL_opennl.h"
typedef struct LaplacianSystem {
bool is_matrix_computed;
@@ -60,18 +65,18 @@ typedef struct LaplacianSystem {
int total_faces;
int total_anchors;
int repeat;
- char anchor_grp_name[64]; /* Vertex Group name*/
- float (*co)[3]; /* Original vertex coordinates*/
- float (*no)[3]; /* Original vertex normal*/
- float (*delta)[3]; /* Differential Coordinates*/
+ char anchor_grp_name[64]; /* Vertex Group name */
+ float (*co)[3]; /* Original vertex coordinates */
+ float (*no)[3]; /* Original vertex normal */
+ float (*delta)[3]; /* Differential Coordinates */
unsigned int (*faces)[4]; /* Copy of MFace (tessface) v1-v4 */
- int *index_anchors; /* Static vertex index list*/
- int *unit_verts; /* Unit vectors of projected edges onto the plane orthogonal to n*/
- int *ringf_indices; /* Indices of faces per vertex*/
- int *ringv_indices; /* Indices of neighbors(vertex) per vertex*/
- NLContext *context; /* System for solve general implicit rotations*/
- MeshElemMap *ringf_map; /* Map of faces per vertex*/
- MeshElemMap *ringv_map; /* Map of vertex per vertex*/
+ int *index_anchors; /* Static vertex index list */
+ int *unit_verts; /* Unit vectors of projected edges onto the plane orthogonal to n */
+ int *ringf_indices; /* Indices of faces per vertex */
+ int *ringv_indices; /* Indices of neighbors(vertex) per vertex */
+ NLContext *context; /* System for solve general implicit rotations */
+ MeshElemMap *ringf_map; /* Map of faces per vertex */
+ MeshElemMap *ringv_map; /* Map of vertex per vertex */
} LaplacianSystem;
static LaplacianSystem *newLaplacianSystem(void)
@@ -125,6 +130,7 @@ static void deleteLaplacianSystem(LaplacianSystem *sys)
MEM_SAFE_FREE(sys->ringv_indices);
MEM_SAFE_FREE(sys->ringf_map);
MEM_SAFE_FREE(sys->ringv_map);
+
if (sys->context) {
nlDeleteContext(sys->context);
}
@@ -140,11 +146,13 @@ static float cotan_weight(const float v1[3], const float v2[3], const float v3[3
cross_v3_v3v3(c, a, b);
clen = len_v3(c);
- if (clen < FLT_EPSILON) {
+
+ if (clen > FLT_EPSILON) {
+ return dot_v3v3(a, b) / clen;
+ }
+ else {
return 0.0f;
}
-
- return dot_v3v3(a, b) / clen;
}
static void createFaceRingMap(
@@ -225,33 +233,33 @@ static void createVertRingMap(
}
/**
-* This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
-* The Linear system is LV = d
-* Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
-* The Laplacian Matrix is computes as a
-* Lij = sum(Wij) (if i == j)
-* Lij = Wij (if i != j)
-* Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
-*
-* The Differential Coordinate is computes as a
-* di = Vi * sum(Wij) - sum(Wij * Vj)
-* Where :
-* di is the Differential Coordinate i
-* sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
-* sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
-*
-* This Laplacian Matrix is described in the paper:
-* Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
-* New York, USA
-*
-* The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
-* Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
-* Conference on Graphics Patterns and Images, SIBGRAPI, 2013
-*
-* The computation of Differential Coordinates is described in the paper:
-* Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
-* 2004. p. 179-188.
-*/
+ * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
+ * The Linear system is LV = d
+ * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
+ * The Laplacian Matrix is computes as a
+ * Lij = sum(Wij) (if i == j)
+ * Lij = Wij (if i != j)
+ * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
+ *
+ * The Differential Coordinate is computes as a
+ * di = Vi * sum(Wij) - sum(Wij * Vj)
+ * Where :
+ * di is the Differential Coordinate i
+ * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
+ * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
+ *
+ * This Laplacian Matrix is described in the paper:
+ * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
+ * New York, USA
+ *
+ * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
+ * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
+ * Conference on Graphics Patterns and Images, SIBGRAPI, 2013
+ *
+ * The computation of Differential Coordinates is described in the paper:
+ * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
+ * 2004. p. 179-188.
+ */
static void initLaplacianMatrix(LaplacianSystem *sys)
{
float v1[3], v2[3], v3[3], v4[3], no[3];
@@ -270,12 +278,12 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
has_4_vert = vidf[3] ? 1 : 0;
if (has_4_vert) {
- normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
+ normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
add_v3_v3(sys->no[idv4], no);
i = 4;
- }
+ }
else {
- normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
+ normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
i = 3;
}
add_v3_v3(sys->no[idv1], no);
@@ -332,14 +340,14 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
nlMatrixAdd(idv1, idv2, -w2);
nlMatrixAdd(idv1, idv3, -w3);
nlMatrixAdd(idv1, idv1, w2 + w3 + w4);
-
+
}
}
}
static void computeImplictRotations(LaplacianSystem *sys)
{
- int vid, * vidn = NULL;
+ int vid, *vidn = NULL;
float minj, mjt, qj[3], vj[3];
int i, j, ln;
@@ -371,10 +379,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
int *fidn;
for (i = 0; i < sys->total_verts; i++) {
- copy_v3_v3(pi, sys->co[i]);
- copy_v3_v3(ni, sys->no[i]);
+ copy_v3_v3(pi, sys->co[i]);
+ copy_v3_v3(ni, sys->no[i]);
k = sys->unit_verts[i];
- copy_v3_v3(pj, sys->co[k]);
+ copy_v3_v3(pj, sys->co[k]);
sub_v3_v3v3(uij, pj, pi);
mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
sub_v3_v3(uij, dun);
@@ -388,7 +396,7 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
pi[0] = nlGetVariable(0, i);
pi[1] = nlGetVariable(1, i);
pi[2] = nlGetVariable(2, i);
- ni[0] = 0.0f; ni[1] = 0.0f; ni[2] = 0.0f;
+ zero_v3(ni);
num_fni = 0;
num_fni = sys->ringf_map[i].count;
for (fi = 0; fi < num_fni; fi++) {
@@ -407,10 +415,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
if (lvin == 3) {
normal_tri_v3(fni, vn[0], vn[1], vn[2]);
- }
+ }
else if (lvin == 4) {
normal_quad_v3(fni, vn[0], vn[1], vn[2], vn[3]);
- }
+ }
add_v3_v3(ni, fni);
}
@@ -428,7 +436,7 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
nlRightHandSideSet(0, i, fni[0]);
nlRightHandSideSet(1, i, fni[1]);
nlRightHandSideSet(2, i, fni[2]);
- }
+ }
else {
nlRightHandSideSet(0, i, sys->delta[i][0]);
nlRightHandSideSet(1, i, sys->delta[i][1]);
@@ -485,7 +493,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
nlEnd(NL_SYSTEM);
if (nlSolveAdvanced(NULL, NL_TRUE)) {
sys->has_solution = true;
-
+
for (j = 1; j <= sys->repeat; j++) {
nlBegin(NL_SYSTEM);
nlBegin(NL_MATRIX);
@@ -510,18 +518,18 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
vertexCos[vid][0] = nlGetVariable(0, vid);
vertexCos[vid][1] = nlGetVariable(1, vid);
vertexCos[vid][2] = nlGetVariable(2, vid);
- }
- }
+ }
+ }
else {
sys->has_solution = false;
}
-
- }
+
+ }
else {
sys->has_solution = false;
}
sys->is_matrix_computed = true;
- }
+ }
else {
if (!sys->has_solution) {
return;
@@ -570,12 +578,12 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
vertexCos[vid][0] = nlGetVariable(0, vid);
vertexCos[vid][1] = nlGetVariable(1, vid);
vertexCos[vid][2] = nlGetVariable(2, vid);
- }
- }
+ }
+ }
else {
sys->has_solution = false;
}
- }
+ }
else {
sys->has_solution = false;
}
@@ -620,9 +628,9 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
}
DM_ensure_tessface(dm);
total_anchors = STACK_SIZE(index_anchors);
- lmd->cacheSystem = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
+ lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
total_anchors, lmd->anchor_grp_name, lmd->repeat);
- sys = (LaplacianSystem *)lmd->cacheSystem;
+ sys = (LaplacianSystem *)lmd->cache_system;
memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors);
memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts);
MEM_freeN(index_anchors);
@@ -655,7 +663,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Deriv
float wpaint;
MDeformVert *dvert = NULL;
MDeformVert *dv = NULL;
- LaplacianSystem *sys = (LaplacianSystem *)lmd->cacheSystem;
+ LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
if (sys->total_verts != numVerts) {
return LAPDEFORM_SYSTEM_CHANGE_VERTEXES;
@@ -664,7 +672,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Deriv
return LAPDEFORM_SYSTEM_CHANGE_EDGES;
}
if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) {
- return LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP;
+ return LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP;
}
modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index);
if (!dvert) {
@@ -694,18 +702,18 @@ static void LaplacianDeformModifier_do(
LaplacianSystem *sys = NULL;
filevertexCos = NULL;
if (!(lmd->flag & MOD_LAPLACIANDEFORM_BIND)) {
- if (lmd->cacheSystem) {
- sys = lmd->cacheSystem;
+ if (lmd->cache_system) {
+ sys = lmd->cache_system;
deleteLaplacianSystem(sys);
- lmd->cacheSystem = NULL;
+ lmd->cache_system = NULL;
}
lmd->total_verts = 0;
MEM_SAFE_FREE(lmd->vertexco);
return;
}
- if (lmd->cacheSystem) {
+ if (lmd->cache_system) {
sysdif = isSystemDifferent(lmd, ob, dm, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
if (sysdif) {
if (sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS || sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP) {
filevertexCos = MEM_mallocN(sizeof(float[3]) * numVerts, "TempModDeformCoordinates");
@@ -713,23 +721,26 @@ static void LaplacianDeformModifier_do(
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
deleteLaplacianSystem(sys);
+ lmd->cache_system = NULL;
initSystem(lmd, ob, dm, filevertexCos, numVerts);
- sys = lmd->cacheSystem; /* may have been reallocated */
+ sys = lmd->cache_system; /* may have been reallocated */
MEM_SAFE_FREE(filevertexCos);
- laplacianDeformPreview(sys, vertexCos);
+ if (sys) {
+ laplacianDeformPreview(sys, vertexCos);
+ }
}
else {
if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) {
- modifier_setError(&lmd->modifier, "Verts changed from %d to %d", lmd->total_verts, numVerts);
- }
+ modifier_setError(&lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts);
+ }
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) {
modifier_setError(&lmd->modifier, "Edges changed from %d to %d", sys->total_edges, dm->getNumEdges(dm));
- }
+ }
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) {
- modifier_setError(&lmd->modifier, "Vertex group %s is not valid", sys->anchor_grp_name);
+ modifier_setError(&lmd->modifier, "Vertex group '%s' is not valid", sys->anchor_grp_name);
}
}
- }
+ }
else {
sys->repeat = lmd->repeat;
laplacianDeformPreview(sys, vertexCos);
@@ -743,24 +754,32 @@ static void LaplacianDeformModifier_do(
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
initSystem(lmd, ob, dm, filevertexCos, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
MEM_SAFE_FREE(filevertexCos);
laplacianDeformPreview(sys, vertexCos);
}
- }
+ }
else {
if (isValidVertexGroup(lmd, ob, dm)) {
initSystem(lmd, ob, dm, vertexCos, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
laplacianDeformPreview(sys, vertexCos);
}
}
}
if (sys->is_matrix_computed && !sys->has_solution) {
- modifier_setError(&lmd->modifier, "The system not found a solution.");
+ modifier_setError(&lmd->modifier, "The system did not find a solution");
}
}
+#else /* WITH_OPENNL */
+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;
+}
+#endif /* WITH_OPENNL */
static void initData(ModifierData *md)
{
@@ -769,7 +788,7 @@ static void initData(ModifierData *md)
lmd->total_verts = 0;
lmd->repeat = 1;
lmd->vertexco = NULL;
- lmd->cacheSystem = NULL;
+ lmd->cache_system = NULL;
lmd->flag = 0;
}
@@ -781,7 +800,7 @@ static void copyData(ModifierData *md, ModifierData *target)
tlmd->repeat = lmd->repeat;
BLI_strncpy(tlmd->anchor_grp_name, lmd->anchor_grp_name, sizeof(tlmd->anchor_grp_name));
tlmd->vertexco = MEM_dupallocN(lmd->vertexco);
- tlmd->cacheSystem = MEM_dupallocN(lmd->cacheSystem);
+ tlmd->cache_system = MEM_dupallocN(lmd->cache_system);
tlmd->flag = lmd->flag;
}
@@ -810,14 +829,14 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
dm->release(dm);
}
}
-
+
static void deformVertsEM(
ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
LaplacianDeformModifier_do((LaplacianDeformModifierData *)md, ob, dm,
- vertexCos, numVerts);
+ vertexCos, numVerts);
if (dm != derivedData) {
dm->release(dm);
}
@@ -826,11 +845,12 @@ static void deformVertsEM(
static void freeData(ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
- LaplacianSystem *sys = (LaplacianSystem *)(lmd->cacheSystem);
-
+#ifdef WITH_OPENNL
+ LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
if (sys) {
deleteLaplacianSystem(sys);
}
+#endif
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 3843ee6f535..f97818a02d4 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -50,6 +50,8 @@
#include "MOD_modifiertypes.h"
#include "MOD_util.h"
+#ifdef WITH_OPENNL
+
#include "ONL_opennl.h"
#if 0
@@ -195,52 +197,6 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
return sys;
}
-static void init_data(ModifierData *md)
-{
- LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
- smd->lambda = 0.01f;
- smd->lambda_border = 0.01f;
- smd->repeat = 1;
- smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME | MOD_LAPLACIANSMOOTH_NORMALIZED;
- smd->defgrp_name[0] = '\0';
-}
-
-static void copy_data(ModifierData *md, ModifierData *target)
-{
- LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
- LaplacianSmoothModifierData *tsmd = (LaplacianSmoothModifierData *) target;
-
- tsmd->lambda = smd->lambda;
- tsmd->lambda_border = smd->lambda_border;
- tsmd->repeat = smd->repeat;
- tsmd->flag = smd->flag;
- BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name));
-}
-
-static bool is_disabled(ModifierData *md, int UNUSED(useRenderParams))
-{
- LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
- short flag;
-
- flag = smd->flag & (MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z);
-
- /* disable if modifier is off for X, Y and Z or if factor is 0 */
- if (flag == 0) return 1;
-
- return 0;
-}
-
-static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md)
-{
- LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *)md;
- CustomDataMask dataMask = 0;
-
- /* ask for vertexgroups if we need them */
- if (smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
-
- return dataMask;
-}
-
static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4)
{
float areaq;
@@ -663,7 +619,61 @@ static void laplaciansmoothModifier_do(
nlDeleteContext(sys->context);
sys->context = NULL;
delete_laplacian_system(sys);
+}
+
+#else /* WITH_OPENNL */
+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;
+}
+#endif /* WITH_OPENNL */
+static void init_data(ModifierData *md)
+{
+ LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
+ smd->lambda = 0.01f;
+ smd->lambda_border = 0.01f;
+ smd->repeat = 1;
+ smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME | MOD_LAPLACIANSMOOTH_NORMALIZED;
+ smd->defgrp_name[0] = '\0';
+}
+
+static void copy_data(ModifierData *md, ModifierData *target)
+{
+ LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
+ LaplacianSmoothModifierData *tsmd = (LaplacianSmoothModifierData *) target;
+
+ tsmd->lambda = smd->lambda;
+ tsmd->lambda_border = smd->lambda_border;
+ tsmd->repeat = smd->repeat;
+ tsmd->flag = smd->flag;
+ BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name));
+}
+
+static bool is_disabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
+ short flag;
+
+ flag = smd->flag & (MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z);
+
+ /* disable if modifier is off for X, Y and Z or if factor is 0 */
+ if (flag == 0) return 1;
+
+ return 0;
+}
+
+static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md)
+{
+ LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if (smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
+
+ return dataMask;
}
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index f3d5157a6ef..85a50473527 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -34,26 +34,29 @@
/* Screw modifier: revolves the edges about an axis */
+#include <limits.h>
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BLI_math.h"
+#include "BLI_alloca.h"
#include "BLI_utildefines.h"
-
#include "BKE_cdderivedmesh.h"
#include "depsgraph_private.h"
#include "MOD_modifiertypes.h"
#include "MEM_guardedalloc.h"
+#include "BLI_strict_flags.h"
+
/* used for gathering edge connectivity */
typedef struct ScrewVertConnect {
float dist; /* distance from the center axis */
float co[3]; /* loaction relative to the transformed axis */
float no[3]; /* calc normal of the vertex */
- int v[2]; /* 2 verts on either side of this one */
+ unsigned int v[2]; /* 2 verts on either side of this one */
MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */
char flag;
} ScrewVertConnect;
@@ -61,18 +64,20 @@ typedef struct ScrewVertConnect {
typedef struct ScrewVertIter {
ScrewVertConnect *v_array;
ScrewVertConnect *v_poin;
- int v;
- int v_other;
+ unsigned int v, v_other;
MEdge *e;
} ScrewVertIter;
+#define SV_UNUSED (UINT_MAX)
+#define SV_INVALID ((UINT_MAX) - 1)
+#define SV_IS_VALID(v) (v < SV_INVALID)
-static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir)
+static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, unsigned int v_init, unsigned int dir)
{
iter->v_array = array;
iter->v = v_init;
- if (v_init >= 0) {
+ if (SV_IS_VALID(v_init)) {
iter->v_poin = &array[v_init];
iter->v_other = iter->v_poin->v[dir];
iter->e = iter->v_poin->e[!dir];
@@ -94,7 +99,7 @@ static void screwvert_iter_step(ScrewVertIter *iter)
iter->v_other = iter->v;
iter->v = iter->v_poin->v[0];
}
- if (iter->v >= 0) {
+ if (SV_IS_VALID(iter->v)) {
iter->v_poin = &iter->v_array[iter->v];
iter->e = iter->v_poin->e[(iter->v_poin->e[0] == iter->e)];
}
@@ -109,7 +114,7 @@ static void initData(ModifierData *md)
{
ScrewModifierData *ltmd = (ScrewModifierData *) md;
ltmd->ob_axis = NULL;
- ltmd->angle = M_PI * 2.0;
+ ltmd->angle = (float)(M_PI * 2.0);
ltmd->axis = 2;
ltmd->flag = MOD_SCREW_SMOOTH_SHADING;
ltmd->steps = 16;
@@ -143,18 +148,43 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
int *origindex;
int mpoly_index = 0;
- int step;
- int i, j;
+ unsigned int step;
+ unsigned int i, j;
unsigned int i1, i2;
- int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
- const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
- int maxVerts = 0, maxEdges = 0, maxPolys = 0;
- const unsigned int totvert = dm->getNumVerts(dm);
- const unsigned int totedge = dm->getNumEdges(dm);
- const unsigned int totpoly = dm->getNumPolys(dm);
- int *edge_poly_map = NULL;
-
- char axis_char = 'X', close;
+ unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
+ const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
+
+ const int quad_ord[4] = {
+ do_flip ? 3 : 0,
+ do_flip ? 2 : 1,
+ do_flip ? 1 : 2,
+ do_flip ? 0 : 3,
+ };
+ const int quad_ord_ofs[4] = {
+ do_flip ? 2 : 0,
+ do_flip ? 1 : 1,
+ do_flip ? 0 : 2,
+ do_flip ? 3 : 3,
+ };
+
+ unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0;
+ const unsigned int totvert = (unsigned int)dm->getNumVerts(dm);
+ const unsigned int totedge = (unsigned int)dm->getNumEdges(dm);
+ const unsigned int totpoly = (unsigned int)dm->getNumPolys(dm);
+
+ unsigned int *edge_poly_map = NULL; /* orig edge to orig poly */
+ unsigned int *vert_loop_map = NULL; /* orig vert to orig loop */
+
+ /* UV Coords */
+ const unsigned int mloopuv_layers_tot = (unsigned int)CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
+ MLoopUV **mloopuv_layers = BLI_array_alloca(mloopuv_layers, mloopuv_layers_tot);
+ float uv_u_scale;
+ float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX};
+ float uv_v_range_inv;
+ float uv_axis_plane[4];
+
+ char axis_char = 'X';
+ bool close;
float angle = ltmd->angle;
float screw_ofs = ltmd->screw_ofs;
float axis_vec[3] = {0.0f, 0.0f, 0.0f};
@@ -164,11 +194,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
float mtx_tx_inv[4][4]; /* inverted */
float mtx_tmp_a[4][4];
- int vc_tot_linked = 0;
+ unsigned int vc_tot_linked = 0;
short other_axis_1, other_axis_2;
float *tmpf1, *tmpf2;
- int edge_offset;
+ unsigned int edge_offset;
MPoly *mpoly_orig, *mpoly_new, *mp_new;
MLoop *mloop_orig, *mloop_new, *ml_new;
@@ -261,7 +291,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
else {
/* exis char is used by i_rotate*/
- axis_char += ltmd->axis; /* 'X' + axis */
+ axis_char = (char)(axis_char + ltmd->axis); /* 'X' + axis */
/* useful to be able to use the axis vec in some cases still */
zero_v3(axis_vec);
@@ -269,8 +299,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* apply the multiplier */
- angle *= ltmd->iter;
- screw_ofs *= ltmd->iter;
+ angle *= (float)ltmd->iter;
+ screw_ofs *= (float)ltmd->iter;
+ uv_u_scale = 1.0f / (float)(step_tot);
/* multiplying the steps is a bit tricky, this works best */
step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
@@ -300,8 +331,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
(totedge * step_tot); /* -1 because vert edges join */
maxPolys = totedge * (step_tot - 1);
}
+
+ if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) {
+ uv_u_scale = (uv_u_scale / (float)ltmd->iter) * (angle / ((float)M_PI * 2.0f));
+ }
- result = CDDM_from_template(dm, maxVerts, maxEdges, 0, maxPolys * 4, maxPolys);
+ result = CDDM_from_template(dm, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys);
/* copy verts from mesh */
mvert_orig = dm->getVertArray(dm);
@@ -313,13 +348,38 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
medge_new = result->getEdgeArray(result);
if (!CustomData_has_layer(&result->polyData, CD_ORIGINDEX)) {
- CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, maxPolys);
+ CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys);
}
origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
- DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
-
+ DM_copy_vert_data(dm, result, 0, 0, (int)totvert); /* copy first otherwise this overwrites our own vertex normals */
+
+ if (mloopuv_layers_tot) {
+ float zero_co[3] = {0};
+ plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec);
+ }
+
+ if (mloopuv_layers_tot) {
+ unsigned int uv_lay;
+ for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
+ mloopuv_layers[uv_lay] = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, (int)uv_lay);
+ }
+
+ if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
+ for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) {
+ const float v = dist_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
+ uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
+ uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
+ }
+ uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]);
+ uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]);
+ }
+
+ uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0];
+ uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f;
+ }
+
/* Set the locations of the first set of verts */
mv_new = mvert_new;
@@ -342,13 +402,20 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
mpoly_orig = dm->getPolyArray(dm);
mloop_orig = dm->getLoopArray(dm);
edge_poly_map = MEM_mallocN(sizeof(*edge_poly_map) * totedge, __func__);
- fill_vn_i(edge_poly_map, totedge, -1);
+ memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge);
+
+ vert_loop_map = MEM_mallocN(sizeof(*vert_loop_map) * totvert, __func__);
+ memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert);
for (i = 0, mp_orig = mpoly_orig; i < totpoly; i++, mp_orig++) {
- MLoop *ml_orig = &mloop_orig[mp_orig->loopstart];
- int j;
- for (j = 0; j < mp_orig->totloop; j++, ml_orig++) {
+ unsigned int loopstart = (unsigned int)mp_orig->loopstart;
+ unsigned int loopend = loopstart + (unsigned int)mp_orig->totloop;
+
+ MLoop *ml_orig = &mloop_orig[loopstart];
+ unsigned int k;
+ for (k = loopstart; k < loopend; k++, ml_orig++) {
edge_poly_map[ml_orig->e] = i;
+ vert_loop_map[ml_orig->v] = k;
/* also order edges based on faces */
if (medge_new[ml_orig->e].v1 != ml_orig->v) {
@@ -410,7 +477,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
vc->flag = 0;
vc->e[0] = vc->e[1] = NULL;
- vc->v[0] = vc->v[1] = -1;
+ vc->v[0] = vc->v[1] = SV_UNUSED;
mul_m4_v3(mtx_tx, vc->co);
/* length in 2d, don't sqrt because this is only for comparison */
@@ -428,7 +495,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
vc->flag = 0;
vc->e[0] = vc->e[1] = NULL;
- vc->v[0] = vc->v[1] = -1;
+ vc->v[0] = vc->v[1] = SV_UNUSED;
/* length in 2d, don't sqrt because this is only for comparison */
vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] +
@@ -442,31 +509,31 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
for (i = 0; i < totedge; i++, med_new++) {
vc = &vert_connect[med_new->v1];
- if (vc->v[0] == -1) { /* unused */
+ if (vc->v[0] == SV_UNUSED) { /* unused */
vc->v[0] = med_new->v2;
vc->e[0] = med_new;
}
- else if (vc->v[1] == -1) {
+ else if (vc->v[1] == SV_UNUSED) {
vc->v[1] = med_new->v2;
vc->e[1] = med_new;
}
else {
- vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */
+ vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
}
vc = &vert_connect[med_new->v2];
/* same as above but swap v1/2 */
- if (vc->v[0] == -1) { /* unused */
+ if (vc->v[0] == SV_UNUSED) { /* unused */
vc->v[0] = med_new->v1;
vc->e[0] = med_new;
}
- else if (vc->v[1] == -1) {
+ else if (vc->v[1] == SV_UNUSED) {
vc->v[1] = med_new->v1;
vc->e[1] = med_new;
}
else {
- vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */
+ vc->v[0] = vc->v[1] = SV_INVALID; /* error value - don't use, 3 edges on vert */
}
}
@@ -477,12 +544,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
* so resulting faces are flipped the right way */
vc_tot_linked = 0; /* count the number of linked verts for this loop */
if (vc->flag == 0) {
- int v_best = -1, ed_loop_closed = 0; /* vert and vert new */
+ unsigned int v_best = SV_UNUSED, ed_loop_closed = 0; /* vert and vert new */
ScrewVertIter lt_iter;
float fl = -1.0f;
/* compiler complains if not initialized, but it should be initialized below */
- int ed_loop_flip = 0;
+ bool ed_loop_flip = false;
/*printf("Loop on connected vert: %i\n", i);*/
@@ -496,7 +563,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/*printf("\t\tVERT: %i\n", lt_iter.v);*/
if (lt_iter.v_poin->flag) {
/*printf("\t\t\tBreaking Found end\n");*/
- //endpoints[0] = endpoints[1] = -1;
+ //endpoints[0] = endpoints[1] = SV_UNUSED;
ed_loop_closed = 1; /* circle */
break;
}
@@ -518,7 +585,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* now we have a collection of used edges. flip their edges the right way*/
- /*if (v_best != -1) - */
+ /*if (v_best != SV_UNUSED) - */
/*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/
@@ -532,7 +599,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* edge connects on each side! */
- if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) {
+ if (SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1])) {
/*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
/* find out which is higher */
@@ -561,7 +628,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
}
}
- else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */
+ else if (SV_IS_VALID(vc_tmp->v[0])) { /*vertex only connected on 1 side */
/*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/
if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */
ed_loop_flip = 1;
@@ -602,7 +669,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* If this is the vert off the best vert and
* the best vert has 2 edges connected too it
* then swap the flip direction */
- if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1))
+ if (j == 1 && SV_IS_VALID(vc_tmp->v[0]) && SV_IS_VALID(vc_tmp->v[1]))
ed_loop_flip = !ed_loop_flip;
while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) {
@@ -647,8 +714,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
*
* calculate vertex normals that can be propagated on lathing
* use edge connectivity work this out */
- if (vc->v[0] >= 0) {
- if (vc->v[1] >= 0) {
+ if (SV_IS_VALID(vc->v[0])) {
+ if (SV_IS_VALID(vc->v[1])) {
/* 2 edges connedted */
/* make 2 connecting vert locations relative to the middle vert */
sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co);
@@ -714,12 +781,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* Add Faces */
for (step = 1; step < step_tot; step++) {
- const int varray_stride = totvert * step;
+ const unsigned int varray_stride = totvert * step;
float step_angle;
float nor_tx[3];
float mat[4][4];
/* Rotation Matrix */
- step_angle = (angle / (step_tot - (!close))) * step;
+ step_angle = (angle / (float)(step_tot - (!close))) * (float)step;
if (ltmd->ob_axis) {
axis_angle_normalized_to_mat3(mat3, axis_vec, step_angle);
@@ -735,7 +802,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot - 1)));
/* copy a slice */
- DM_copy_vert_data(dm, result, 0, varray_stride, totvert);
+ DM_copy_vert_data(dm, result, 0, (int)varray_stride, (int)totvert);
mv_new_base = mvert_new;
mv_new = &mvert_new[varray_stride]; /* advance to the next slice */
@@ -782,7 +849,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (close) {
/* last loop of edges, previous loop dosnt account for the last set of edges */
- const int varray_stride = (step_tot - 1) * totvert;
+ const unsigned int varray_stride = (step_tot - 1) * totvert;
for (i = 0; i < totvert; i++) {
med_new->v1 = i;
@@ -800,97 +867,134 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
edge_offset = totedge + (totvert * (step_tot - (close ? 0 : 1)));
for (i = 0; i < totedge; i++, med_new_firstloop++) {
+ const unsigned int step_last = step_tot - (close ? 1 : 2);
+ const unsigned int mpoly_index_orig = totpoly ? edge_poly_map[i] : UINT_MAX;
+ const bool has_mpoly_orig = (mpoly_index_orig != UINT_MAX);
+ float uv_v_offset_a, uv_v_offset_b;
+
+ const unsigned int mloop_index_orig[2] = {
+ vert_loop_map ? vert_loop_map[medge_new[i].v1] : UINT_MAX,
+ vert_loop_map ? vert_loop_map[medge_new[i].v2] : UINT_MAX,
+ };
+ const bool has_mloop_orig = mloop_index_orig[0] != UINT_MAX;
+
short mat_nr;
/* for each edge, make a cylinder of quads */
i1 = med_new_firstloop->v1;
i2 = med_new_firstloop->v2;
- if (totpoly && (edge_poly_map[i] != -1)) {
- mat_nr = mpoly_orig[edge_poly_map[i]].mat_nr;
+ if (has_mpoly_orig) {
+ mat_nr = mpoly_orig[mpoly_index_orig].mat_nr;
}
else {
mat_nr = 0;
}
- for (step = 0; step < step_tot - 1; step++) {
-
- /* new face */
- if (do_flip) {
- ml_new[3].v = i1;
- ml_new[2].v = i2;
- ml_new[1].v = i2 + totvert;
- ml_new[0].v = i1 + totvert;
-
- ml_new[2].e = step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1;
- ml_new[1].e = totedge + i2;
- ml_new[0].e = edge_offset + step + (i * (step_tot - 1));
- ml_new[3].e = totedge + i1;
- }
- else {
- ml_new[0].v = i1;
- ml_new[1].v = i2;
- ml_new[2].v = i2 + totvert;
- ml_new[3].v = i1 + totvert;
-
- ml_new[0].e = step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1;
- ml_new[1].e = totedge + i2;
- ml_new[2].e = edge_offset + step + (i * (step_tot - 1));
- ml_new[3].e = totedge + i1;
+ if (has_mloop_orig == false && mloopuv_layers_tot) {
+ uv_v_offset_a = dist_to_plane_v3(mvert_new[medge_new[i].v1].co, uv_axis_plane);
+ uv_v_offset_b = dist_to_plane_v3(mvert_new[medge_new[i].v2].co, uv_axis_plane);
+
+ if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
+ uv_v_offset_a = (uv_v_offset_a - uv_v_minmax[0]) * uv_v_range_inv;
+ uv_v_offset_b = (uv_v_offset_b - uv_v_minmax[0]) * uv_v_range_inv;
}
+ }
+ for (step = 0; step <= step_last; step++) {
+ /* Polygon */
+ if (has_mpoly_orig) {
+ DM_copy_poly_data(dm, result, (int)mpoly_index_orig, (int)mpoly_index, 1);
+ origindex[mpoly_index] = (int)mpoly_index_orig;
+ }
+ else {
+ origindex[mpoly_index] = ORIGINDEX_NONE;
+ mp_new->flag = mpoly_flag;
+ mp_new->mat_nr = mat_nr;
+ }
mp_new->loopstart = mpoly_index * 4;
mp_new->totloop = 4;
- mp_new->mat_nr = mat_nr;
- mp_new->flag = mpoly_flag;
- origindex[mpoly_index] = ORIGINDEX_NONE;
- mp_new++;
- ml_new += 4;
- mpoly_index++;
-
- /* new vertical edge */
- if (step) { /* The first set is already dome */
- med_new->v1 = i1;
- med_new->v2 = i2;
- med_new->flag = med_new_firstloop->flag;
- med_new->crease = med_new_firstloop->crease;
- med_new++;
+
+
+ /* Loop-Custom-Data */
+ if (has_mloop_orig) {
+ int l_index = (int)(ml_new - mloop_new);
+ DM_copy_loop_data(dm, result, (int)mloop_index_orig[0], l_index + 0, 1);
+ DM_copy_loop_data(dm, result, (int)mloop_index_orig[1], l_index + 1, 1);
+ DM_copy_loop_data(dm, result, (int)mloop_index_orig[1], l_index + 2, 1);
+ DM_copy_loop_data(dm, result, (int)mloop_index_orig[0], l_index + 3, 1);
+
+ if (mloopuv_layers_tot) {
+ unsigned int uv_lay;
+ const float uv_u_offset_a = (float)(step) * uv_u_scale;
+ const float uv_u_offset_b = (float)(step + 1) * uv_u_scale;
+ for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
+ MLoopUV *mluv = &mloopuv_layers[uv_lay][l_index];
+
+ mluv[quad_ord[0]].uv[0] += uv_u_offset_a;
+ mluv[quad_ord[1]].uv[0] += uv_u_offset_a;
+ mluv[quad_ord[2]].uv[0] += uv_u_offset_b;
+ mluv[quad_ord[3]].uv[0] += uv_u_offset_b;
+ }
+ }
}
- i1 += totvert;
- i2 += totvert;
- }
-
- /* close the loop*/
- if (close) {
- if (do_flip) {
- ml_new[3].v = i1;
- ml_new[2].v = i2;
- ml_new[1].v = med_new_firstloop->v2;
- ml_new[0].v = med_new_firstloop->v1;
-
- ml_new[2].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
- ml_new[1].e = totedge + i2;
- ml_new[0].e = i;
- ml_new[3].e = totedge + i1;
+ else {
+ if (mloopuv_layers_tot) {
+ int l_index = (int)(ml_new - mloop_new);
+
+ unsigned int uv_lay;
+ const float uv_u_offset_a = (float)(step) * uv_u_scale;
+ const float uv_u_offset_b = (float)(step + 1) * uv_u_scale;
+ for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
+ MLoopUV *mluv = &mloopuv_layers[uv_lay][l_index];
+
+ copy_v2_fl2(mluv[quad_ord[0]].uv, uv_u_offset_a, uv_v_offset_a);
+ copy_v2_fl2(mluv[quad_ord[1]].uv, uv_u_offset_a, uv_v_offset_b);
+ copy_v2_fl2(mluv[quad_ord[2]].uv, uv_u_offset_b, uv_v_offset_b);
+ copy_v2_fl2(mluv[quad_ord[3]].uv, uv_u_offset_b, uv_v_offset_a);
+ }
+ }
+ }
+
+ /* Loop-Data */
+ if (!(close && step == step_last)) {
+ /* regular segments */
+ ml_new[quad_ord[0]].v = i1;
+ ml_new[quad_ord[1]].v = i2;
+ ml_new[quad_ord[2]].v = i2 + totvert;
+ ml_new[quad_ord[3]].v = i1 + totvert;
+
+ ml_new[quad_ord_ofs[0]].e = step == 0 ? i : (edge_offset + step + (i * (step_tot - 1))) - 1;
+ ml_new[quad_ord_ofs[1]].e = totedge + i2;
+ ml_new[quad_ord_ofs[2]].e = edge_offset + step + (i * (step_tot - 1));
+ ml_new[quad_ord_ofs[3]].e = totedge + i1;
+
+
+ /* new vertical edge */
+ if (step) { /* The first set is already done */
+ med_new->v1 = i1;
+ med_new->v2 = i2;
+ med_new->flag = med_new_firstloop->flag;
+ med_new->crease = med_new_firstloop->crease;
+ med_new++;
+ }
+ i1 += totvert;
+ i2 += totvert;
}
else {
- ml_new[0].v = i1;
- ml_new[1].v = i2;
- ml_new[2].v = med_new_firstloop->v2;
- ml_new[3].v = med_new_firstloop->v1;
-
- ml_new[0].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
- ml_new[1].e = totedge + i2;
- ml_new[2].e = i;
- ml_new[3].e = totedge + i1;
+ /* last segment */
+ ml_new[quad_ord[0]].v = i1;
+ ml_new[quad_ord[1]].v = i2;
+ ml_new[quad_ord[2]].v = med_new_firstloop->v2;
+ ml_new[quad_ord[3]].v = med_new_firstloop->v1;
+
+ ml_new[quad_ord_ofs[0]].e = (edge_offset + step + (i * (step_tot - 1))) - 1;
+ ml_new[quad_ord_ofs[1]].e = totedge + i2;
+ ml_new[quad_ord_ofs[2]].e = i;
+ ml_new[quad_ord_ofs[3]].e = totedge + i1;
}
- mp_new->loopstart = mpoly_index * 4;
- mp_new->totloop = 4;
- mp_new->mat_nr = mat_nr;
- mp_new->flag = mpoly_flag;
- origindex[mpoly_index] = ORIGINDEX_NONE;
mp_new++;
ml_new += 4;
mpoly_index++;
@@ -907,10 +1011,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* validate loop edges */
#if 0
{
- i = 0;
+ unsigned i = 0;
printf("\n");
for (; i < maxPolys * 4; i += 4) {
- int ii;
+ unsigned int ii;
ml_new = mloop_new + i;
ii = findEd(medge_new, maxEdges, ml_new[0].v, ml_new[1].v);
printf("%d %d -- ", ii, ml_new[0].e);
@@ -936,6 +1040,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
MEM_freeN(edge_poly_map);
}
+ if (vert_loop_map) {
+ MEM_freeN(vert_loop_map);
+ }
+
if ((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
result->dirty |= DM_DIRTY_NORMALS;
}
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 61c8cb5655d..64feb0068cb 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -133,6 +133,7 @@ set(SRC
shader/nodes/node_shader_geom.c
shader/nodes/node_shader_hueSatVal.c
shader/nodes/node_shader_invert.c
+ shader/nodes/node_shader_lamp.c
shader/nodes/node_shader_mapping.c
shader/nodes/node_shader_material.c
shader/nodes/node_shader_math.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 853046a2a23..71c0638829f 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -47,6 +47,7 @@ void register_node_type_sh_group(void);
void register_node_type_sh_output(void);
void register_node_type_sh_material(void);
void register_node_type_sh_camera(void);
+void register_node_type_sh_lamp(void);
void register_node_type_sh_value(void);
void register_node_type_sh_rgb(void);
void register_node_type_sh_mix_rgb(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index db9f710b6cf..beeaa7787fb 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -56,6 +56,7 @@ DefNode( ShaderNode, SH_NODE_MAPPING, def_sh_mapping, "MAPPI
DefNode( ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", VectorCurve, "Vector Curves", "" )
DefNode( ShaderNode, SH_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", RGBCurve, "RGB Curves", "" )
DefNode( ShaderNode, SH_NODE_CAMERA, 0, "CAMERA", CameraData, "Camera Data", "" )
+DefNode( ShaderNode, SH_NODE_LAMP, def_sh_lamp, "LAMP", LampData, "Lamp Data", "" )
DefNode( ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode( ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
DefNode( ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 31ae46468c3..d05a5da5f1c 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -218,6 +218,16 @@ static void update(bNodeTree *ntree)
}
}
+static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode)
+{
+ /* Composite node will only show previews for input classes
+ * by default, other will be hidden
+ * but can be made visible with the show_preview option */
+ if (bnode->typeinfo->nclass != NODE_CLASS_INPUT) {
+ bnode->flag &= ~NODE_PREVIEW;
+ }
+}
+
bNodeTreeType *ntreeType_Composite;
void register_node_tree_type_cmp(void)
@@ -238,6 +248,7 @@ void register_node_tree_type_cmp(void)
tt->local_merge = local_merge;
tt->update = update;
tt->get_from_context = composite_get_from_context;
+ tt->node_add_init = composite_node_add_init;
tt->ext.srna = &RNA_CompositorNodeTree;
diff --git a/source/blender/nodes/shader/nodes/node_shader_lamp.c b/source/blender/nodes/shader/nodes/node_shader_lamp.c
new file mode 100644
index 00000000000..adf53ba9b52
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_lamp.c
@@ -0,0 +1,86 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/shader/nodes/node_shader_lamp.c
+ * \ingroup shdnodes
+ */
+
+
+#include "node_shader_util.h"
+
+/* **************** LAMP INFO ******************** */
+static bNodeSocketTemplate sh_node_lamp_out[] = {
+ { SOCK_RGBA, 0, N_("Color")},
+ { SOCK_VECTOR, 0, N_("Light Vector")},
+ { SOCK_FLOAT, 0, N_("Distance")},
+ { SOCK_RGBA, 0, N_("Shadow")},
+ { SOCK_FLOAT, 0, N_("Visibility Factor")},
+ { -1, 0, "" }
+};
+
+
+static void node_shader_exec_lamp(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
+{
+ if (data) {
+ Object *ob = (Object *)node->id;
+
+ if (ob) {
+ ShadeInput *shi = ((ShaderCallData *)data)->shi;
+
+ shi->nodes = 1; /* temp hack to prevent trashadow recursion */
+ out[4]->vec[0] = RE_lamp_get_data(shi, ob, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec);
+ shi->nodes = 0;
+ }
+ }
+}
+
+static int gpu_shader_lamp(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (node->id) {
+ GPULamp *lamp = GPU_lamp_from_blender(GPU_material_scene(mat), (Object *)node->id, NULL);
+ GPUNodeLink *col, *lv, *dist, *visifac, *shadow;
+
+ visifac = GPU_lamp_get_data(mat, lamp, &col, &lv, &dist, &shadow);
+
+ return GPU_stack_link(mat, "lamp", in, out, col, lv, dist, shadow, visifac);
+ }
+
+ return 0;
+}
+
+void register_node_type_sh_lamp(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_LAMP, "Lamp Data", NODE_CLASS_INPUT, 0);
+ node_type_compatibility(&ntype, NODE_OLD_SHADING);
+ node_type_socket_templates(&ntype, NULL, sh_node_lamp_out);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_lamp);
+ node_type_gpu(&ntype, gpu_shader_lamp);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index 9b9c3cf705b..832ce582b4b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -31,6 +31,7 @@
static bNodeSocketTemplate sh_node_layer_weight_in[] = {
{ SOCK_FLOAT, 1, N_("Blend"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
@@ -40,9 +41,12 @@ static bNodeSocketTemplate sh_node_layer_weight_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return 0;
+ if (!in[1].link)
+ in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
+
+ return GPU_stack_link(mat, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
index 707e295241a..2c515d587c0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
@@ -44,13 +44,26 @@ static bNodeSocketTemplate sh_node_sephsv_out[] = {
{ -1, 0, "" }
};
+static void node_shader_exec_sephsv(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+{
+ rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2],
+ &out[0]->vec[0], &out[1]->vec[0], &out[2]->vec[0]);
+}
+
+static int gpu_shader_sephsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "separate_hsv", in, out);
+}
+
void register_node_type_sh_sephsv(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 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_sephsv_in, sh_node_sephsv_out);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv);
+ node_type_gpu(&ntype, gpu_shader_sephsv);
nodeRegisterType(&ntype);
}
@@ -68,13 +81,26 @@ static bNodeSocketTemplate sh_node_combhsv_out[] = {
{ -1, 0, "" }
};
+static void node_shader_exec_combhsv(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
+{
+ hsv_to_rgb(in[0]->vec[0], in[1]->vec[0], in[2]->vec[0],
+ &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]);
+}
+
+static int gpu_shader_combhsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "combine_hsv", in, out);
+}
+
void register_node_type_sh_combhsv(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 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_combhsv_in, sh_node_combhsv_out);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv);
+ node_type_gpu(&ntype, gpu_shader_combhsv);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 0ac0285031e..a5b52a3dd63 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -183,8 +183,13 @@ if env['WITH_BF_SMOKE']:
if env['WITH_BF_COLLADA']:
defs.append('WITH_COLLADA')
-if env['WITH_BF_OIIO']:
+if env['WITH_BF_OCIO']:
defs.append('WITH_OCIO')
+ incs += ' ' + '#/intern/opencolorio'
+
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OPENIMAGEIO')
+ incs += ' ../imbuf/intern/oiio'
if env['WITH_BF_PLAYER']:
defs.append('WITH_PLAYER')
diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt
index b15923a87d2..c7b86acc8f9 100644
--- a/source/blender/python/bmesh/CMakeLists.txt
+++ b/source/blender/python/bmesh/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC_SYS
set(SRC
bmesh_py_api.c
+ bmesh_py_geometry.c
bmesh_py_ops.c
bmesh_py_ops_call.c
bmesh_py_types.c
@@ -42,6 +43,7 @@ set(SRC
bmesh_py_utils.c
bmesh_py_api.h
+ bmesh_py_geometry.h
bmesh_py_ops.h
bmesh_py_ops_call.h
bmesh_py_types.h
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index c7b10d0aa4b..bc14e1ac3a6 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -42,6 +42,7 @@
#include "bmesh_py_ops.h"
#include "bmesh_py_utils.h"
+#include "bmesh_py_geometry.h"
#include "BKE_editmesh.h"
@@ -201,5 +202,9 @@ PyObject *BPyInit_bmesh(void)
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
+ PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry()));
+ PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ Py_INCREF(submodule);
+
return mod;
}
diff --git a/source/blender/python/bmesh/bmesh_py_geometry.c b/source/blender/python/bmesh/bmesh_py_geometry.c
new file mode 100644
index 00000000000..4cd0a3951b3
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_geometry.c
@@ -0,0 +1,110 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/bmesh/bmesh_py_geometry.c
+ * \ingroup pybmesh
+ *
+ * This file defines the 'bmesh.geometry' module.
+ * Utility functions for operating on 'bmesh.types'
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "bmesh.h"
+#include "bmesh_py_types.h"
+#include "bmesh_py_geometry.h" /* own include */
+
+PyDoc_STRVAR(bpy_bm_geometry_intersect_face_point_doc,
+".. method:: intersect_face_point(face, point)\n"
+"\n"
+" Tests if a point is inside a face (using the faces normal).\n"
+"\n"
+" :arg face: The face to test.\n"
+" :type face: :class:`bmesh.types.BMFace`\n"
+" :arg point: The point to test.\n"
+" :type point: float triplet\n"
+" :return: True when the the point is in the face.\n"
+" :rtype: bool\n"
+);
+static PyObject *bpy_bm_geometry_intersect_face_point(BPy_BMFace *UNUSED(self), PyObject *args)
+{
+ BPy_BMFace *py_face;
+ PyObject *py_point;
+ float point[3];
+ bool ret;
+
+ if (!PyArg_ParseTuple(args,
+ "O!O:intersect_face_point",
+ &BPy_BMFace_Type, &py_face,
+ &py_point))
+ {
+ return NULL;
+ }
+
+ BPY_BM_CHECK_OBJ(py_face);
+ if (mathutils_array_parse(point, 3, 3, py_point, "intersect_face_point") == -1) {
+ return NULL;
+ }
+
+ ret = BM_face_point_inside_test(py_face->f, point);
+
+ return PyBool_FromLong(ret);
+}
+
+
+static struct PyMethodDef BPy_BM_geometry_methods[] = {
+ {"intersect_face_point", (PyCFunction)bpy_bm_geometry_intersect_face_point, METH_VARARGS, bpy_bm_geometry_intersect_face_point_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+
+PyDoc_STRVAR(BPy_BM_utils_doc,
+"This module provides access to bmesh geometry evaluation functions."
+);
+static struct PyModuleDef BPy_BM_geometry_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bmesh.geometry", /* m_name */
+ BPy_BM_utils_doc, /* m_doc */
+ 0, /* m_size */
+ BPy_BM_geometry_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+
+PyObject *BPyInit_bmesh_geometry(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPy_BM_geometry_module_def);
+
+ return submodule;
+}
diff --git a/source/blender/python/bmesh/bmesh_py_geometry.h b/source/blender/python/bmesh/bmesh_py_geometry.h
new file mode 100644
index 00000000000..c0c455f79cd
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_geometry.h
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/bmesh/bmesh_py_geometry.h
+ * \ingroup pybmesh
+ */
+
+#ifndef __BMESH_PY_GEOMETRY_H__
+#define __BMESH_PY_GEOMETRY_H__
+
+PyObject *BPyInit_bmesh_geometry(void);
+
+#endif /* __BMESH_PY_GEOMETRY_H__ */
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 5b5438defee..768c5506b8c 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -180,7 +180,7 @@ static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text))
return NULL;
- BLF_width_and_height(fontid, text, &r_width, &r_height);
+ 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));
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index ef5d26dccdc..0605f408348 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -35,6 +35,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/cycles/blender
+ ../../../../intern/opencolorio
../../../../intern/guardedalloc
)
@@ -49,6 +50,8 @@ set(SRC
bpy_app_ffmpeg.c
bpy_app_build_options.c
bpy_app_handlers.c
+ bpy_app_ocio.c
+ bpy_app_oiio.c
bpy_app_translations.c
bpy_driver.c
bpy_interface.c
@@ -73,6 +76,8 @@ set(SRC
bpy_app_ffmpeg.h
bpy_app_build_options.h
bpy_app_handlers.h
+ bpy_app_ocio.h
+ bpy_app_oiio.h
bpy_app_translations.h
bpy_driver.h
bpy_intern_string.h
@@ -242,6 +247,13 @@ if(WITH_OPENCOLORIO)
add_definitions(-DWITH_OCIO)
endif()
+if(WITH_OPENIMAGEIO)
+ add_definitions(-DWITH_OPENIMAGEIO)
+ list(APPEND INC
+ ../../imbuf/intern/oiio
+ )
+endif()
+
if(WITH_PLAYER)
add_definitions(-DWITH_PLAYER)
endif()
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 21767196e11..795015c42a0 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -34,6 +34,8 @@
#include "bpy_app.h"
#include "bpy_app_ffmpeg.h"
+#include "bpy_app_ocio.h"
+#include "bpy_app_oiio.h"
#include "bpy_app_build_options.h"
#include "bpy_app_translations.h"
@@ -93,6 +95,8 @@ static PyStructSequence_Field app_info_fields[] = {
/* submodules */
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
+ {(char *)"ocio", (char *)"OpenColorIO library information backend"},
+ {(char *)"oiio", (char *)"OpenImageIO library information backend"},
{(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
{(char *)"handlers", (char *)"Application handler callbacks"},
{(char *)"translations", (char *)"Application and addons internationalization API"},
@@ -167,6 +171,8 @@ static PyObject *make_app_info(void)
#endif
SetObjItem(BPY_app_ffmpeg_struct());
+ SetObjItem(BPY_app_ocio_struct());
+ SetObjItem(BPY_app_oiio_struct());
SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
SetObjItem(BPY_app_translations_struct());
diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c
new file mode 100644
index 00000000000..eff52bc9dae
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_ocio.c
@@ -0,0 +1,112 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_ocio.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_ocio.h"
+
+#ifdef WITH_OCIO
+# include "ocio_capi.h"
+#endif
+
+static PyTypeObject BlenderAppOCIOType;
+
+static PyStructSequence_Field app_ocio_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenColorIO support")},
+ {(char *)("version"), (char *)("The OpenColorIO version as a tuple of 3 numbers")},
+ {(char *)("version_string"), (char *)("The OpenColorIO version formatted as a string")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_ocio_info_desc = {
+ (char *)"bpy.app.ocio", /* name */
+ (char *)"This module contains information about OpenColorIO blender is linked against", /* doc */
+ app_ocio_info_fields, /* fields */
+ (sizeof(app_ocio_info_fields) / sizeof(PyStructSequence_Field)) - 1
+};
+
+static PyObject *make_ocio_info(void)
+{
+ PyObject *ocio_info;
+ int pos = 0;
+
+#ifdef WITH_OCIO
+ int curversion;
+#endif
+
+ ocio_info = PyStructSequence_New(&BlenderAppOCIOType);
+ if (ocio_info == NULL) {
+ return NULL;
+ }
+
+#ifndef WITH_OCIO
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(ocio_info, pos++, PyUnicode_FromString(str))
+#endif
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(ocio_info, pos++, obj)
+
+#ifdef WITH_OCIO
+ curversion = OCIO_getVersionHex();
+ SetObjItem(PyBool_FromLong(1));
+ SetObjItem(Py_BuildValue("(iii)",
+ curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+ SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+#else
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetStrItem("Unknown");
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(ocio_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return ocio_info;
+}
+
+PyObject *BPY_app_ocio_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppOCIOType, &app_ocio_info_desc);
+
+ ret = make_ocio_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppOCIOType.tp_init = NULL;
+ BlenderAppOCIOType.tp_new = NULL;
+ BlenderAppOCIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_ocio.h b/source/blender/python/intern/bpy_app_ocio.h
new file mode 100644
index 00000000000..ff230b4ba66
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_ocio.h
@@ -0,0 +1,32 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_ocio.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_OCIO_H__
+#define __BPY_APP_OCIO_H__
+
+PyObject *BPY_app_ocio_struct(void);
+
+#endif /* __BPY_APP_OCIO_H__ */
diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c
new file mode 100644
index 00000000000..b5f0f321c6d
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_oiio.c
@@ -0,0 +1,112 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_oiio.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_oiio.h"
+
+#ifdef WITH_OPENIMAGEIO
+# include "openimageio_api.h"
+#endif
+
+static PyTypeObject BlenderAppOIIOType;
+
+static PyStructSequence_Field app_oiio_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenImageIO support")},
+ {(char *)("version"), (char *)("The OpenImageIO version as a tuple of 3 numbers")},
+ {(char *)("version_string"), (char *)("The OpenImageIO version formatted as a string")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_oiio_info_desc = {
+ (char *)"bpy.app.oiio", /* name */
+ (char *)"This module contains information about OpeImageIO blender is linked against", /* doc */
+ app_oiio_info_fields, /* fields */
+ (sizeof(app_oiio_info_fields) / sizeof(PyStructSequence_Field)) - 1
+};
+
+static PyObject *make_oiio_info(void)
+{
+ PyObject *oiio_info;
+ int pos = 0;
+
+#ifdef WITH_OPENIMAGEIO
+ int curversion;
+#endif
+
+ oiio_info = PyStructSequence_New(&BlenderAppOIIOType);
+ if (oiio_info == NULL) {
+ return NULL;
+ }
+
+#ifndef WITH_OPENIMAGEIO
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(oiio_info, pos++, PyUnicode_FromString(str))
+#endif
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(oiio_info, pos++, obj)
+
+#ifdef WITH_OPENIMAGEIO
+ curversion = OIIO_getVersionHex();
+ SetObjItem(PyBool_FromLong(1));
+ SetObjItem(Py_BuildValue("(iii)",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+#else
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetStrItem("Unknown");
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(oiio_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return oiio_info;
+}
+
+PyObject *BPY_app_oiio_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppOIIOType, &app_oiio_info_desc);
+
+ ret = make_oiio_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppOIIOType.tp_init = NULL;
+ BlenderAppOIIOType.tp_new = NULL;
+ BlenderAppOIIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_oiio.h b/source/blender/python/intern/bpy_app_oiio.h
new file mode 100644
index 00000000000..775fed237f2
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_oiio.h
@@ -0,0 +1,32 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_oiio.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_OIIO_H__
+#define __BPY_APP_OIIO_H__
+
+PyObject *BPY_app_oiio_struct(void);
+
+#endif /* __BPY_APP_OIIO_H__ */
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index cc1dd369f8b..7a3d56dc56d 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -219,6 +219,7 @@ static struct _inittab bpy_internal_modules[] = {
{(char *)"bmesh", BPyInit_bmesh},
// {(char *)"bmesh.types", BPyInit_bmesh_types},
// {(char *)"bmesh.utils", BPyInit_bmesh_utils},
+ // {(char *)"bmesh.utils", BPyInit_bmesh_geometry},
#ifdef WITH_AUDASPACE
{(char *)"aud", AUD_initPython},
#endif
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 754952cd65f..e867aa00958 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -313,6 +313,7 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
char *opname;
PyObject *kw = NULL; /* optional args */
int all_args = 1;
+ int macro_args = 1;
int error_val = 0;
char *buf = NULL;
@@ -325,7 +326,7 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
+ if (!PyArg_ParseTuple(args, "s|O!ii:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args, &macro_args))
return NULL;
ot = WM_operatortype_find(opname, true);
@@ -345,7 +346,7 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
if (error_val == 0)
- buf = WM_operator_pystring_ex(C, NULL, all_args, ot, &ptr);
+ buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr);
WM_operator_properties_free(&ptr);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 3e5dcc28903..ccff114a56d 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -378,7 +378,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* will overwrite error */
PyErr_SetString(PyExc_TypeError,
"Matrix(): "
- "expects no args or 2-4 numeric sequences");
+ "expects no args or a single arg containing 2-4 numeric sequences");
return NULL;
}
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 584861d4c49..53e428cf73c 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -576,12 +576,14 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
{
VectorObject *line_a, *line_b, *plane_co, *plane_no;
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))
+ &vector_Type, &plane_no,
+ &no_flip))
{
return NULL;
}
@@ -601,6 +603,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
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);
}
@@ -633,7 +636,7 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
float isect_co[3];
float isect_no[3];
- if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_plane_plane",
+ 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,
@@ -970,9 +973,9 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
"\n"
" :arg pt: Point\n"
" :type pt: :class:`mathutils.Vector`\n"
-" :arg plane_co: First point of the quad\n"
+" :arg plane_co: A point on the plane\n"
" :type plane_co: :class:`mathutils.Vector`\n"
-" :arg plane_no: Second point of the quad\n"
+" :arg plane_no: The direction the plane is facing\n"
" :type plane_no: :class:`mathutils.Vector`\n"
" :rtype: float\n"
);
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index 8cf91e44c77..0c193df3861 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -242,14 +242,17 @@ void filepath_qt(char *string, RenderData *rd)
BLI_path_abs(string, G.main->name);
BLI_make_existing_file(string);
-
- if (!BLI_testextensie(string, ".mov")) {
- /* if we don't have any #'s to insert numbers into, use 4 numbers by default */
- if (strchr(string, '#')==NULL)
- strcat(string, "####"); /* 4 numbers */
- BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
- strcat(string, ".mov");
+ if (rd->scemode & R_EXTENSION) {
+ if (!BLI_testextensie(string, ".mov")) {
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ strcat(string, ".mov");
+ }
+ }
+ else {
+ if (BLI_path_frame_check_chars(string)) {
+ BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+ }
}
}
diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h
index 35e424b9081..a499cd462b7 100644
--- a/source/blender/quicktime/quicktime_export.h
+++ b/source/blender/quicktime/quicktime_export.h
@@ -46,7 +46,7 @@
typedef struct QuicktimeCodecTypeDesc {
int codecType;
int rnatmpvalue;
- char * codecName;
+ char *codecName;
} QuicktimeCodecTypeDesc;
// quicktime movie output functions
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index baec1a74721..dbde29ea7ac 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -194,6 +194,7 @@ struct Tex;
struct MTex;
struct ImBuf;
struct ImagePool;
+struct Object;
/* this one uses nodes */
int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage);
@@ -203,11 +204,11 @@ int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres
int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres,
const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex,
struct ImagePool *pool);
+float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]);
/* shaded view and bake */
struct Render;
struct Image;
-struct Object;
int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update, float *progress);
struct Image *RE_bake_shade_get_image(void);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index fb9f96b0ef7..52030fb2d86 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -2819,6 +2819,19 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
}
}
+ if (dl->flag & DL_CYCL_V && orco) {
+ fp = dl->verts;
+ nr = dl->nr;
+ while (nr--) {
+ ver = RE_findOrAddVert(obr, obr->totvert++);
+ copy_v3_v3(ver->co, fp);
+ mul_m4_v3(mat, ver->co);
+ ver->orco = orco;
+ fp += 3;
+ orco += 3;
+ }
+ }
+
if (dl->bevelSplitFlag || timeoffset==0) {
const int startvlak= obr->totvlak;
@@ -2832,6 +2845,11 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
p3+= startvert;
p4+= startvert;
+ if (dl->flag & DL_CYCL_V && orco && a == dl->parts - 1) {
+ p3 = p1 + dl->nr;
+ p4 = p2 + dl->nr;
+ }
+
for (; b<dl->nr; b++) {
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
/* important 1 offset in order is kept [#24913] */
@@ -3775,9 +3793,9 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
lar->spotsi= la->spotsize;
if (lar->mode & LA_HALO) {
- if (lar->spotsi>170.0f) lar->spotsi= 170.0f;
+ if (lar->spotsi > DEG2RADF(170.0f)) lar->spotsi = DEG2RADF(170.0f);
}
- lar->spotsi= cosf( (float)M_PI*lar->spotsi/360.0f );
+ lar->spotsi= cosf(lar->spotsi * 0.5f);
lar->spotbl= (1.0f-lar->spotsi)*la->spotblend;
memcpy(lar->mtex, la->mtex, MAX_MTEX*sizeof(void *));
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 37587d89ce0..487de42515d 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -1124,7 +1124,13 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
*/
if (ibuf->rect) {
if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
- IMB_float_from_rect(ibuf);
+ if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
+ /* Higher depth bits are supported but not needed for current file output. */
+ ibuf->rect_float = NULL;
+ }
+ else {
+ IMB_float_from_rect(ibuf);
+ }
}
else {
/* ensure no float buffer remained from previous frame */
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index e8127b0e6b9..049d7e5a732 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3558,12 +3558,15 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
/* strip material copy from unsupported flags */
for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
- if (mat->septex & (1<<tex_nr)) continue;
if (mat->mtex[tex_nr]) {
MTex *mtex = mat->mtex[tex_nr];
- if (!mtex->tex) continue;
+ /* just in case make all non-used mtexes empty*/
+ Tex *cur_tex = mtex->tex;
+ mtex->tex = NULL;
+
+ if (mat->septex & (1<<tex_nr) || !cur_tex) continue;
/* only keep compatible texflags */
mtex->texflag = mtex->texflag & (MTEX_RGBTOINT | MTEX_STENCIL | MTEX_NEGATIVE | MTEX_ALPHAMIX);
@@ -3598,7 +3601,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
}
/* copy texture */
- tex= mtex->tex = localize_texture(mtex->tex);
+ tex= mtex->tex = localize_texture(cur_tex);
/* update texture anims */
BKE_animsys_evaluate_animdata(scene, &tex->id, tex->adt, BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
@@ -3646,7 +3649,8 @@ void RE_free_sample_material(Material *mat)
}
}
- BKE_material_free(mat);
+ /* don't update user counts as we are freeing a duplicate */
+ BKE_material_free_ex(mat, false);
MEM_freeN(mat);
}
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index dbc9c47446f..6cb34a67f45 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -228,7 +228,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
maxz*= lar->sh_zfac;
maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
- if (fabsf(nray[2]) < FLT_EPSILON) {
+ if (fabs(nray[2]) < FLT_EPSILON) {
use_yco = TRUE;
}
}
@@ -1982,3 +1982,94 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shr->combined[3]= shr->alpha;
}
+/* used for "Lamp Data" shader node */
+static float lamp_get_data_internal(ShadeInput *shi, GroupObject *go, float col[4], float lv[3], float *dist, float shadow[4])
+{
+ LampRen *lar = go->lampren;
+ float visifac, inp;
+
+ if (!lar || lar->type == LA_YF_PHOTON
+ || ((lar->mode & LA_LAYER) && (lar->lay & shi->obi->lay) == 0)
+ || (lar->lay & shi->lay) == 0)
+ return 0.0f;
+
+ if (lar->mode & LA_TEXTURE)
+ do_lamp_tex(lar, lv, shi, col, LA_TEXTURE);
+
+ visifac = lamp_get_visibility(lar, shi->co, lv, dist);
+
+ if (visifac == 0.0f
+ || lar->type == LA_HEMI
+ || (lar->type != LA_SPOT && !(lar->mode & LA_SHAD_RAY))
+ || (R.r.scemode & R_BUTS_PREVIEW))
+ return visifac;
+
+ inp = dot_v3v3(shi->vn, lv);
+
+ if (inp > 0.0f) {
+ float shadfac[4];
+
+ shadow[0] = lar->shdwr;
+ shadow[1] = lar->shdwg;
+ shadow[2] = lar->shdwb;
+
+ if (lar->mode & LA_SHAD_TEX)
+ do_lamp_tex(lar, lv, shi, shadow, LA_SHAD_TEX);
+
+ lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
+
+ shadow[0] = 1.0f - ((1.0f - shadfac[0] * shadfac[3]) * (1.0f - shadow[0]));
+ shadow[1] = 1.0f - ((1.0f - shadfac[1] * shadfac[3]) * (1.0f - shadow[1]));
+ shadow[2] = 1.0f - ((1.0f - shadfac[2] * shadfac[3]) * (1.0f - shadow[2]));
+ }
+
+ return visifac;
+}
+
+float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4])
+{
+ col[0] = col[1] = col[2] = 0.0f;
+ col[3] = 1.0f;
+ copy_v3_v3(lv, shi->vn);
+ *dist = 1.0f;
+ shadow[0] = shadow[1] = shadow[2] = shadow[3] = 1.0f;
+
+ if (lamp_obj->type == OB_LAMP) {
+ GroupObject *go;
+ Lamp *lamp = (Lamp *)lamp_obj->data;
+
+ col[0] = lamp->r * lamp->energy;
+ col[1] = lamp->g * lamp->energy;
+ col[2] = lamp->b * lamp->energy;
+
+ if (R.r.scemode & R_BUTS_PREVIEW) {
+ for (go = R.lights.first; go; go = go->next) {
+ /* "Lamp.002" is main key light of material preview */
+ if (strcmp(go->ob->id.name + 2, "Lamp.002") == 0)
+ return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+ }
+ return 0.0f;
+ }
+
+ if (shi->light_override) {
+ for (go = shi->light_override->gobject.first; go; go = go->next) {
+ if (go->ob == lamp_obj)
+ return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+ }
+ }
+
+ if (shi->mat && shi->mat->group) {
+ for (go = shi->mat->group->gobject.first; go; go = go->next) {
+ if (go->ob == lamp_obj)
+ return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+ }
+ }
+
+ for (go = R.lights.first; go; go = go->next) {
+ if (go->ob == lamp_obj)
+ return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+ }
+ }
+
+ return 0.0f;
+}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 1f38368399a..d8f558bf2c9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -75,7 +75,7 @@ void WM_init_state_normal_set(void);
void WM_init_native_pixels(bool do_it);
void WM_init (struct bContext *C, int argc, const char **argv);
-void WM_exit_ext (struct bContext *C, const short do_python);
+void WM_exit_ext (struct bContext *C, const bool do_python);
void WM_exit (struct bContext *C) ATTR_NORETURN;
@@ -164,7 +164,7 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
-int WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
+bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
/* notifiers */
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
@@ -182,7 +182,7 @@ void wm_event_init_from_window(struct wmWindow *win, struct wmEvent *event);
/* at maximum, every timestep seconds it triggers event_type events */
struct wmTimer *WM_event_add_timer(struct wmWindowManager *wm, struct wmWindow *win, int event_type, double timestep);
void WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer);
-void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer, int dosleep);
+void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer, bool do_sleep);
/* operator api, default callbacks */
/* invoke callback, uses enum property named "type" */
@@ -235,10 +235,11 @@ int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short c
void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */
void WM_operator_properties_sanitize(struct PointerRNA *ptr, const bool no_context); /* make props context sensitive or not */
-int WM_operator_properties_default(struct PointerRNA *ptr, const bool do_update);
+bool WM_operator_properties_default(struct PointerRNA *ptr, const bool do_update);
void WM_operator_properties_reset(struct wmOperator *op);
void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring);
void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot);
+void WM_operator_properties_clear(struct PointerRNA *ptr);
void WM_operator_properties_free(struct PointerRNA *ptr);
void WM_operator_properties_filesel(struct wmOperatorType *ot, int filter, short type, short action, short flag, short display);
void WM_operator_properties_border(struct wmOperatorType *ot);
@@ -272,9 +273,12 @@ bool WM_operator_last_properties_store(struct wmOperator *op);
/* operator as a python command (resultuing string must be freed) */
-char *WM_operator_pystring_ex(struct bContext *C, struct wmOperator *op, const bool all_args,
+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);
-char *WM_operator_pystring(struct bContext *C, struct wmOperator *op, const bool all_args);
+char *WM_operator_pystring(struct bContext *C, struct wmOperator *op,
+ const bool all_args, const bool macro_args);
+bool WM_operator_pystring_abbreviate(char *str, int str_len_max);
char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
void WM_operator_bl_idname(char *to, const char *from);
void WM_operator_py_idname(char *to, const char *from);
@@ -376,13 +380,13 @@ enum {
struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void *owner, const char *name, int flag, int job_type);
-int WM_jobs_test(struct wmWindowManager *wm, void *owner, int job_type);
+bool WM_jobs_test(struct wmWindowManager *wm, void *owner, int job_type);
float WM_jobs_progress(struct wmWindowManager *wm, void *owner);
char *WM_jobs_name(struct wmWindowManager *wm, void *owner);
void *WM_jobs_customdata(struct wmWindowManager *wm, void *owner);
void *WM_jobs_customdata_from_type(struct wmWindowManager *wm, int job_type);
-int WM_jobs_is_running(struct wmJob *);
+bool WM_jobs_is_running(struct wmJob *);
void *WM_jobs_customdata_get(struct wmJob *);
void WM_jobs_customdata_set(struct wmJob *, void *customdata, void (*free)(void *));
void WM_jobs_timer(struct wmJob *, double timestep, unsigned int note, unsigned int endnote);
@@ -399,14 +403,14 @@ void WM_jobs_kill_all(struct wmWindowManager *wm);
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner);
void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type);
-int WM_jobs_has_running(struct wmWindowManager *wm);
+bool WM_jobs_has_running(struct wmWindowManager *wm);
void WM_job_main_thread_lock_acquire(struct wmJob *job);
void WM_job_main_thread_lock_release(struct wmJob *job);
/* clipboard */
-char *WM_clipboard_text_get(int selection);
-void WM_clipboard_text_set(char *buf, int selection);
+char *WM_clipboard_text_get(bool selection);
+void WM_clipboard_text_set(const char *buf, bool selection);
/* progress */
void WM_progress_set(struct wmWindow *win, float progress);
@@ -418,7 +422,7 @@ void WM_redraw_windows(struct bContext *C);
void WM_main_playanim(int argc, const char **argv);
/* debugging only, convenience function to write on crash */
-int write_crash_blend(void);
+bool write_crash_blend(void);
#ifdef __cplusplus
}
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 4c58089f4e7..dad8e7bdde0 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -217,9 +217,11 @@ static const char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
-
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
/* for multiwin drags, we only do this if mouse inside */
- if (event->x < 0 || event->y < 0 || event->x > win->sizex || event->y > win->sizey)
+ if (event->x < 0 || event->y < 0 || event->x > winsize_x || event->y > winsize_y)
return;
drag->opname[0] = 0;
@@ -257,14 +259,15 @@ void wm_drags_check_ops(bContext *C, wmEvent *event)
static void wm_drop_operator_draw(const char *name, int x, int y)
{
int width = UI_GetStringWidth(name);
+ int padding = 4 * UI_DPI_FAC;
glColor4ub(0, 0, 0, 50);
uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
- uiRoundBox(x, y, x + width + 8, y + 15, 4);
+ uiRoundBox(x, y, x + width + 2 * padding, y + 4 * padding, padding);
glColor4ub(255, 255, 255, 255);
- UI_DrawString(x + 4, y + 4, name);
+ UI_DrawString(x + padding, y + padding, name);
}
static const char *wm_drag_name(wmDrag *drag)
@@ -301,6 +304,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag;
+ const int winsize_y = WM_window_pixels_y(win);
int cursorx, cursory, x, y;
cursorx = win->eventstate->x;
@@ -313,6 +317,8 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
/* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
glEnable(GL_BLEND);
for (drag = wm->drags.first; drag; drag = drag->next) {
+ int iconsize = 16 * UI_DPI_FAC; /* assumed to be 16 pixels */
+ int padding = 4 * UI_DPI_FAC;
/* image or icon */
if (drag->imb) {
@@ -327,29 +333,28 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
}
}
else {
- x = cursorx - 8;
- y = cursory - 2;
+ x = cursorx - 2 * padding;
+ y = cursory - 2 * UI_DPI_FAC;
- /* icons assumed to be 16 pixels */
if (rect)
- drag_rect_minmax(rect, x, y, x + 16, y + 16);
+ drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize);
else
- UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8);
+ UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8);
}
/* item name */
if (drag->imb) {
x = cursorx - drag->sx / 2;
- y = cursory - drag->sy / 2 - 16;
+ y = cursory - drag->sy / 2 - iconsize;
}
else {
- x = cursorx + 10;
- y = cursory + 1;
+ x = cursorx + 10 * UI_DPI_FAC;
+ y = cursory + 1 * UI_DPI_FAC;
}
if (rect) {
int w = UI_GetStringWidth(wm_drag_name(drag));
- drag_rect_minmax(rect, x, y, x + w, y + 16);
+ drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else {
glColor4ub(255, 255, 255, 255);
@@ -360,16 +365,24 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
if (drag->opname[0]) {
if (drag->imb) {
x = cursorx - drag->sx / 2;
- y = cursory + drag->sy / 2 + 4;
+
+ if (cursory + drag->sy / 2 + padding + iconsize < winsize_y)
+ y = cursory + drag->sy / 2 + padding;
+ else
+ y = cursory - drag->sy / 2 - padding - iconsize - padding - iconsize;
}
else {
- x = cursorx - 8;
- y = cursory + 16;
+ x = cursorx - 2 * padding;
+
+ if (cursory + iconsize + iconsize < winsize_y)
+ y = cursory + iconsize;
+ else
+ y = cursory - iconsize - 2 * UI_DPI_FAC;
}
if (rect) {
int w = UI_GetStringWidth(wm_drag_name(drag));
- drag_rect_minmax(rect, x, y, x + w, y + 16);
+ drag_rect_minmax(rect, x, y, x + w, y + iconsize);
}
else
wm_drop_operator_draw(drag->opname, x, y);
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index dac62d624b5..5edc57be40b 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -429,6 +429,9 @@ static void wm_draw_triple_fail(bContext *C, wmWindow *win)
static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
{
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
GLint maxsize;
int x, y;
@@ -437,22 +440,22 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
triple->target = GL_TEXTURE_RECTANGLE_ARB;
triple->nx = 1;
triple->ny = 1;
- triple->x[0] = WM_window_pixels_x(win);
- triple->y[0] = WM_window_pixels_y(win);
+ triple->x[0] = winsize_x;
+ triple->y[0] = winsize_y;
}
else if (GPU_non_power_of_two_support()) {
triple->target = GL_TEXTURE_2D;
triple->nx = 1;
triple->ny = 1;
- triple->x[0] = WM_window_pixels_x(win);
- triple->y[0] = WM_window_pixels_y(win);
+ triple->x[0] = winsize_x;
+ triple->y[0] = winsize_y;
}
else {
triple->target = GL_TEXTURE_2D;
triple->nx = 0;
triple->ny = 0;
- split_width(WM_window_pixels_x(win), MAX_N_TEX, triple->x, &triple->nx);
- split_width(WM_window_pixels_y(win), MAX_N_TEX, triple->y, &triple->ny);
+ split_width(winsize_x, MAX_N_TEX, triple->x, &triple->nx);
+ split_width(winsize_y, MAX_N_TEX, triple->y, &triple->ny);
}
/* generate texture names */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index d60901f1325..8ac8da93584 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -491,8 +491,8 @@ int WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
static void wm_operator_print(bContext *C, wmOperator *op)
{
/* context is needed for enum function */
- char *buf = WM_operator_pystring(C, op, false);
- printf("%s\n", buf);
+ char *buf = WM_operator_pystring(C, op, false, true);
+ puts(buf);
MEM_freeN(buf);
}
@@ -626,7 +626,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int cal
if (op->type->flag & OPTYPE_REGISTER) {
if (G.background == 0) { /* ends up printing these in the terminal, gets annoying */
/* Report the python string representation of the operator */
- char *buf = WM_operator_pystring(C, op, false);
+ char *buf = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
}
@@ -660,7 +660,7 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
if (repeat == 0) {
if (G.debug & G_DEBUG_WM) {
- char *buf = WM_operator_pystring(C, op, false);
+ char *buf = WM_operator_pystring(C, op, false, true);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
}
@@ -890,7 +890,7 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event)
#if 1 /* may want to disable operator remembering previous state for testing */
bool WM_operator_last_properties_init(wmOperator *op)
{
- bool change = false;
+ bool changed = false;
if (op->type->last_properties) {
PropertyRNA *iterprop;
@@ -916,7 +916,7 @@ bool WM_operator_last_properties_init(wmOperator *op)
idp_dst->flag |= IDP_FLAG_GHOST;
IDP_ReplaceInGroup(op->properties, idp_dst);
- change = true;
+ changed = true;
}
}
}
@@ -924,7 +924,7 @@ bool WM_operator_last_properties_init(wmOperator *op)
RNA_PROP_END;
}
- return change;
+ return changed;
}
bool WM_operator_last_properties_store(wmOperator *op)
@@ -2584,7 +2584,7 @@ void WM_event_add_mousemove(bContext *C)
/* for modal callbacks, check configuration for how to interpret exit with tweaks */
-int WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
+bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
{
/* if the release-confirm userpref setting is enabled,
* tweak events can be canceled when mouse is released
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index f7bbb84facc..09192c5c2ec 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -282,7 +282,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
}
/* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef(bContext *C)
+static void wm_init_userdef(bContext *C, const bool from_memory)
{
/* versioning is here */
UI_init_userdef();
@@ -301,6 +301,11 @@ static void wm_init_userdef(bContext *C)
else G.f &= ~G_SCRIPT_AUTOEXEC;
}
+ /* avoid re-saving for every small change to our prefs, allow overrides */
+ if (from_memory) {
+ UI_init_userdef_factory();
+ }
+
/* update tempdir from user preferences */
BLI_init_temporary_dir(U.tempdir);
@@ -433,7 +438,7 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
if (retval == BKE_READ_FILE_OK_USERPREFS) {
/* in case a userdef is read from regular .blend */
- wm_init_userdef(C);
+ wm_init_userdef(C, false);
}
if (retval != BKE_READ_FILE_FAIL) {
@@ -512,19 +517,45 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* called on startup, (context entirely filled with NULLs) */
/* or called for 'New File' */
/* both startup.blend and userpref.blend are checked */
-int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory)
+/* the optional paramater custom_file points to an alterntive startup page */
+/* custom_file can be NULL */
+int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
{
ListBase wmbase;
char startstr[FILE_MAX];
char prefstr[FILE_MAX];
int success = 0;
+ /* Indicates whether user prefereneces were really load from memory.
+ *
+ * This is used for versioning code, and for this we can not rely on from_memory
+ * passed via argument. This is because there might be configuration folder
+ * exists but it might not have userpref.blend and in this case we fallback to
+ * reading home file from memory.
+ *
+ * And in this case versioning code is to be run.
+ */
+ bool read_userdef_from_memory = true;
+
+ /* options exclude eachother */
+ BLI_assert((from_memory && custom_file) == 0);
+
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
G.relbase_valid = 0;
if (!from_memory) {
const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
- if (cfgdir) {
+ if (custom_file) {
+ BLI_strncpy(startstr, custom_file, FILE_MAX);
+
+ if (cfgdir) {
+ BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
+ }
+ else {
+ prefstr[0] = '\0';
+ }
+ }
+ else if (cfgdir) {
BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE);
BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
}
@@ -539,13 +570,12 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
G.fileflags &= ~G_FILE_NO_UI;
/* put aside screens to match with persistent windows later */
- wm_window_match_init(C, &wmbase);
+ wm_window_match_init(C, &wmbase);
if (!from_memory) {
- if (BLI_exists(startstr)) {
+ if (BLI_access(startstr, R_OK) == 0) {
success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL);
}
-
if (U.themes.first == NULL) {
if (G.debug & G_DEBUG)
printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr);
@@ -553,6 +583,11 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
}
}
+ if (success == 0 && custom_file && reports) {
+ BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file);
+ /*We can not return from here because wm is already reset*/
+ }
+
if (success == 0) {
success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true);
if (wmbase.first == NULL) wm_clear_default_size(C);
@@ -568,7 +603,10 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
/* check new prefs only after startup.blend was finished */
if (!from_memory && BLI_exists(prefstr)) {
int done = BKE_read_file_userdef(prefstr, NULL);
- if (done) printf("Read new prefs: %s\n", prefstr);
+ if (done) {
+ read_userdef_from_memory = false;
+ printf("Read new prefs: %s\n", prefstr);
+ }
}
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
@@ -576,7 +614,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
/* check userdef before open window, keymaps etc */
- wm_init_userdef(C);
+ wm_init_userdef(C, read_userdef_from_memory);
/* match the read WM with current WM */
wm_window_match_do(C, &wmbase);
@@ -631,8 +669,23 @@ int wm_history_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
- int from_memory = strcmp(op->type->idname, "WM_OT_read_factory_settings") == 0;
- return wm_homefile_read(C, op->reports, from_memory) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
+ char filepath_buf[FILE_MAX];
+ const char *filepath = NULL;
+
+ if (!from_memory) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_string_get(op->ptr, prop, filepath_buf);
+ filepath = filepath_buf;
+ if (BLI_access(filepath, R_OK)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Can't read alternative start-up file: '%s'", filepath);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void wm_read_history(void)
@@ -793,7 +846,7 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
}
/* easy access from gdb */
-int write_crash_blend(void)
+bool write_crash_blend(void)
{
char path[FILE_MAX];
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */
@@ -924,7 +977,7 @@ int wm_homefile_write_exec(bContext *C, wmOperator *op)
int fileflags;
/* check current window and close it if temp */
- if (win->screen->temp)
+ if (win && win->screen->temp)
wm_window_close(C, wm, win);
/* update keymaps in user preferences */
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 4d4d46d063a..33758d9699d 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -329,19 +329,19 @@ static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt, bool filled)
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
- int winsizex = WM_window_pixels_x(win);
- int winsizey = WM_window_pixels_y(win);
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
glEnable(GL_LINE_STIPPLE);
glColor3ub(96, 96, 96);
glLineStipple(1, 0xCCCC);
- sdrawline(rect->xmin - winsizex, rect->ymin, rect->xmin + winsizex, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsizey, rect->xmin, rect->ymin + winsizey);
+ sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
+ sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
glColor3ub(255, 255, 255);
glLineStipple(1, 0x3333);
- sdrawline(rect->xmin - winsizex, rect->ymin, rect->xmin + winsizex, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsizey, rect->xmin, rect->ymin + winsizey);
+ sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
+ sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
glDisable(GL_LINE_STIPPLE);
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 4e9b849af40..8b43a6af606 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -159,7 +159,7 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_lang_init();
/* get the default database, plus a wm */
- wm_homefile_read(C, NULL, G.factory_startup);
+ wm_homefile_read(C, NULL, G.factory_startup, NULL);
BLF_lang_set(NULL);
@@ -382,7 +382,7 @@ static void wait_for_console_key(void)
/* called in creator.c even... tsk, split this! */
/* note, doesnt run exit() call WM_exit() for that */
-void WM_exit_ext(bContext *C, const short do_python)
+void WM_exit_ext(bContext *C, const bool do_python)
{
wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL;
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 6908588ebd7..7da9a1c09d3 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -222,7 +222,7 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *
}
/* returns true if job runs, for UI (progress) indicators */
-int WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
+bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
{
wmJob *wm_job;
@@ -280,7 +280,7 @@ void *WM_jobs_customdata_from_type(wmWindowManager *wm, int job_type)
return NULL;
}
-int WM_jobs_is_running(wmJob *wm_job)
+bool WM_jobs_is_running(wmJob *wm_job)
{
return wm_job->running;
}
@@ -523,9 +523,9 @@ void WM_jobs_kill(wmWindowManager *wm, void *owner, void (*startjob)(void *, sho
wm_job = wm->jobs.first;
while (wm_job) {
if (wm_job->owner == owner || wm_job->startjob == startjob) {
- wmJob *bill = wm_job;
+ wmJob *wm_job_kill = wm_job;
wm_job = wm_job->next;
- wm_jobs_kill_job(wm, bill);
+ wm_jobs_kill_job(wm, wm_job_kill);
}
else {
wm_job = wm_job->next;
@@ -649,7 +649,7 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
}
}
-int WM_jobs_has_running(wmWindowManager *wm)
+bool WM_jobs_has_running(wmWindowManager *wm)
{
wmJob *wm_job;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 50575095825..ac32d16a23b 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -296,6 +296,11 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
retval = opm->type->modal(C, opm, event);
OPERATOR_RETVAL_CHECK(retval);
+ /* if we're halfway through using a tool and cancel it, clear the options [#37149] */
+ if (retval & OPERATOR_CANCELLED) {
+ WM_operator_properties_clear(opm->ptr);
+ }
+
/* if this one is done but it's not the last operator in the macro */
if ((retval & OPERATOR_FINISHED) && opm->next) {
MacroData *md = op->customdata;
@@ -528,7 +533,8 @@ void WM_operator_bl_idname(char *to, const char *from)
*
* Note: both op and opptr may be NULL (op is only used for macro operators).
*/
-char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, wmOperatorType *ot, PointerRNA *opptr)
+char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args,
+ wmOperatorType *ot, PointerRNA *opptr)
{
char idname_py[OP_MAX_TYPENAME];
@@ -547,7 +553,10 @@ char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args,
/* Special handling for macros, else we only get default values in this case... */
wmOperator *opm;
bool first_op = true;
- for (opm = op->macro.first; opm; opm = opm->next) {
+
+ opm = macro_args ? op->macro.first : NULL;
+
+ for (; opm; opm = opm->next) {
PointerRNA *opmptr = opm->ptr;
PointerRNA opmptr_default;
if (opmptr == NULL) {
@@ -573,13 +582,14 @@ char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args,
else {
/* only to get the orginal props for comparisons */
PointerRNA opptr_default;
+ const bool macro_args_test = ot->macro.first ? macro_args : true;
if (opptr == NULL) {
WM_operator_properties_create_ptr(&opptr_default, ot);
opptr = &opptr_default;
}
- cstring_args = RNA_pointer_as_string_keywords(C, opptr, false, all_args, max_prop_length);
+ cstring_args = RNA_pointer_as_string_keywords(C, opptr, false, all_args, macro_args_test, max_prop_length);
BLI_dynstr_append(dynstr, cstring_args);
MEM_freeN(cstring_args);
@@ -595,9 +605,51 @@ char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args,
return cstring;
}
-char *WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args)
+char *WM_operator_pystring(bContext *C, wmOperator *op,
+ const bool all_args, const bool macro_args)
{
- return WM_operator_pystring_ex(C, op, all_args, op->type, op->ptr);
+ return WM_operator_pystring_ex(C, op, all_args, macro_args, op->type, op->ptr);
+}
+
+
+/**
+ * \return true if the string was shortened
+ */
+bool WM_operator_pystring_abbreviate(char *str, int str_len_max)
+{
+ const int str_len = strlen(str);
+ const char *parens_start = strchr(str, '(');
+
+ if (parens_start) {
+ const int parens_start_pos = parens_start - str;
+ const char *parens_end = strrchr(parens_start + 1, ')');
+
+ if (parens_end) {
+ const int parens_len = parens_end - parens_start;
+
+ if (parens_len > str_len_max) {
+ const char *comma_first = strchr(parens_start, ',');
+
+ /* truncate after the first comma */
+ if (comma_first) {
+ const char end_str[] = " ... )";
+ const int end_str_len = sizeof(end_str) - 1;
+
+ /* leave a place for the first argument*/
+ const int new_str_len = (comma_first - parens_start) + 1;
+
+ if (str_len >= new_str_len + parens_start_pos + end_str_len + 1) {
+ /* append " ... )" to the string after the comma */
+ memcpy(str + new_str_len + parens_start_pos, end_str, end_str_len + 1);
+
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
}
/* return NULL if no match is found */
@@ -863,9 +915,9 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
* \note, theres nothing specific to operators here.
* this could be made a general function.
*/
-int WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
+bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
{
- int is_change = FALSE;
+ bool changed = false;
RNA_STRUCT_BEGIN (ptr, prop)
{
switch (RNA_property_type(prop)) {
@@ -874,14 +926,14 @@ int WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
StructRNA *ptype = RNA_property_pointer_type(ptr, prop);
if (ptype != &RNA_Struct) {
PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
- is_change |= WM_operator_properties_default(&opptr, do_update);
+ changed |= WM_operator_properties_default(&opptr, do_update);
}
break;
}
default:
if ((do_update == false) || (RNA_property_is_set(ptr, prop) == FALSE)) {
if (RNA_property_reset(ptr, prop, -1)) {
- is_change = 1;
+ changed = true;
}
}
break;
@@ -889,7 +941,7 @@ int WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
}
RNA_STRUCT_END;
- return is_change;
+ return changed;
}
/* remove all props without PROP_SKIP_SAVE */
@@ -912,6 +964,15 @@ void WM_operator_properties_reset(wmOperator *op)
}
}
+void WM_operator_properties_clear(PointerRNA *ptr)
+{
+ IDProperty *properties = ptr->data;
+
+ if (properties) {
+ IDP_ClearProperty(properties);
+ }
+}
+
void WM_operator_properties_free(PointerRNA *ptr)
{
IDProperty *properties = ptr->data;
@@ -1688,8 +1749,8 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLI_snprintf(date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time);
BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi);
- hash_width = (int)BLF_width(style->widgetlabel.uifont_id, hash_buf) + 0.5f * U.widget_unit;
- date_width = (int)BLF_width(style->widgetlabel.uifont_id, date_buf) + 0.5f * U.widget_unit;
+ hash_width = (int)BLF_width(style->widgetlabel.uifont_id, hash_buf, sizeof(hash_buf)) + 0.5f * U.widget_unit;
+ date_width = (int)BLF_width(style->widgetlabel.uifont_id, date_buf, sizeof(date_buf)) + 0.5f * U.widget_unit;
#endif /* WITH_BUILDINFO */
block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
@@ -1715,7 +1776,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
char branch_buf[128] = "\0";
int branch_width;
BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch);
- branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf) + 0.5f * U.widget_unit;
+ branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) + 0.5f * U.widget_unit;
uiDefBut(block, LABEL, 0, branch_buf, U.pixelsize * 494 - branch_width, U.pixelsize * (258 - label_delta), branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
}
#endif /* WITH_BUILDINFO */
@@ -1800,7 +1861,7 @@ static void WM_OT_splash(wmOperatorType *ot)
{
ot->name = "Splash Screen";
ot->idname = "WM_OT_splash";
- ot->description = "Opens the splash screen with release info";
+ ot->description = "Open the splash screen with release info";
ot->invoke = wm_splash_invoke;
ot->poll = WM_operator_winactive;
@@ -1937,7 +1998,6 @@ static void WM_OT_save_homefile(wmOperatorType *ot)
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_write_exec;
- ot->poll = WM_operator_winactive;
}
static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
@@ -1954,7 +2014,6 @@ static void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot)
ot->description = "Add path to exclude from autoexecution";
ot->exec = wm_userpref_autoexec_add_exec;
- ot->poll = WM_operator_winactive;
ot->flag = OPTYPE_INTERNAL;
}
@@ -1976,7 +2035,6 @@ static void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot)
ot->description = "Remove path to exclude from autoexecution";
ot->exec = wm_userpref_autoexec_remove_exec;
- ot->poll = WM_operator_winactive;
ot->flag = OPTYPE_INTERNAL;
@@ -1991,7 +2049,6 @@ static void WM_OT_save_userpref(wmOperatorType *ot)
ot->invoke = WM_operator_confirm;
ot->exec = wm_userpref_write_exec;
- ot->poll = WM_operator_winactive;
}
static void WM_OT_read_history(wmOperatorType *ot)
@@ -2009,12 +2066,19 @@ static void WM_OT_read_history(wmOperatorType *ot)
static void WM_OT_read_homefile(wmOperatorType *ot)
{
+ PropertyRNA *prop;
ot->name = "Reload Start-Up File";
ot->idname = "WM_OT_read_homefile";
ot->description = "Open the default file (doesn't save the current file)";
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
+
+ prop = RNA_def_string_file_path(ot->srna, "filepath", "",
+ FILE_MAX, "File Path",
+ "Path to an alternative start-up file");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
/* ommit poll to run in background mode */
}
@@ -2443,7 +2507,6 @@ static void WM_OT_recover_last_session(wmOperatorType *ot)
ot->description = "Open the last closed file (\"" BLENDER_QUIT_FILE "\")";
ot->exec = wm_recover_last_session_exec;
- ot->poll = WM_operator_winactive;
}
/* *************** recover auto save **************** */
@@ -2488,7 +2551,6 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
ot->exec = wm_recover_auto_save_exec;
ot->invoke = wm_recover_auto_save_invoke;
- ot->poll = WM_operator_winactive;
WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_LONGDISPLAY);
@@ -2646,6 +2708,15 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
RNA_string_set(op->ptr, "filepath", name);
+ /* if we're saving for the first time and prefer relative paths - any existign paths will be absolute,
+ * enable the option to remap paths to avoid confusion [#37240] */
+ if ((G.relbase_valid == false) && (U.flag & USER_RELPATHS)) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "relative_remap");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ }
+
if (G.save_over) {
if (BLI_exists(name)) {
uiPupMenuSaveOver(C, op, name);
@@ -2707,7 +2778,6 @@ static void WM_OT_quit_blender(wmOperatorType *ot)
ot->invoke = WM_operator_confirm;
ot->exec = wm_exit_blender_exec;
- ot->poll = WM_operator_winactive;
}
/* *********************** */
@@ -3942,6 +4012,8 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
static void WM_OT_radial_control(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
ot->name = "Radial Control";
ot->idname = "WM_OT_radial_control";
ot->description = "Set some size property (like e.g. brush size) with mouse wheel";
@@ -3953,15 +4025,32 @@ static void WM_OT_radial_control(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* all paths relative to the context */
- RNA_def_string(ot->srna, "data_path_primary", "", 0, "Primary Data Path", "Primary path of property to be set by the radial control");
- RNA_def_string(ot->srna, "data_path_secondary", "", 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
- RNA_def_string(ot->srna, "use_secondary", "", 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
- RNA_def_string(ot->srna, "rotation_path", "", 0, "Rotation Path", "Path of property used to rotate the texture display");
- RNA_def_string(ot->srna, "color_path", "", 0, "Color Path", "Path of property used to set the color of the control");
- RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control");
- RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control");
- RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control");
- RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
+ prop = RNA_def_string(ot->srna, "data_path_primary", "", 0, "Primary Data Path", "Primary path of property to be set by the radial control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "data_path_secondary", "", 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "use_secondary", "", 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "rotation_path", "", 0, "Rotation Path", "Path of property used to rotate the texture display");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "color_path", "", 0, "Color Path", "Path of property used to set the color of the control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ************************** timer for testing ***************** */
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index a02fc75a3fb..8456be3d5c4 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -895,17 +895,20 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
break;
case 's':
- sfra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+ sfra = atoi(argv[2]);
+ CLAMP(sfra, 1, MAXFRAME);
argc--;
argv++;
break;
case 'e':
- efra = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]) ));
+ efra = atoi(argv[2]);
+ CLAMP(efra, 1, MAXFRAME);
argc--;
argv++;
break;
case 'j':
- ps.fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2])));
+ ps.fstep = atoi(argv[2]);
+ CLAMP(ps.fstep, 1, MAXFRAME);
swaptime *= ps.fstep;
argc--;
argv++;
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index ae535ed45e8..75608a850ac 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -209,6 +209,9 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct)
wmSubWindow *swin = swin_from_swinid(win, swinid);
if (swin) {
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
int width, height;
swin->winrct = *winrct;
@@ -226,10 +229,10 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct)
* fixed it). - zr (2001!)
*/
- if (swin->winrct.xmax > WM_window_pixels_x(win))
- swin->winrct.xmax = WM_window_pixels_x(win);
- if (swin->winrct.ymax > WM_window_pixels_y(win))
- swin->winrct.ymax = WM_window_pixels_y(win);
+ if (swin->winrct.xmax > winsize_x)
+ swin->winrct.xmax = winsize_x;
+ if (swin->winrct.ymax > winsize_y)
+ swin->winrct.ymax = winsize_y;
/* extra service */
wmSubWindowSet(win, swinid);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 5f344340643..d3936ff32e2 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1137,7 +1137,7 @@ void wm_ghost_exit(void)
/* **************** timer ********************** */
/* to (de)activate running timers temporary */
-void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer, int dosleep)
+void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer, bool do_sleep)
{
wmTimer *wt;
@@ -1146,7 +1146,7 @@ void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *t
break;
if (wt)
- wt->sleep = dosleep;
+ wt->sleep = do_sleep;
}
wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
@@ -1199,7 +1199,7 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
/* ******************* clipboard **************** */
-char *WM_clipboard_text_get(int selection)
+char *WM_clipboard_text_get(bool selection)
{
char *p, *p2, *buf, *newbuf;
@@ -1224,7 +1224,7 @@ char *WM_clipboard_text_get(int selection)
return newbuf;
}
-void WM_clipboard_text_set(char *buf, int selection)
+void WM_clipboard_text_set(const char *buf, bool selection)
{
if (!G.background) {
#ifdef _WIN32
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 9fda6801925..526696138a5 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -35,7 +35,7 @@ void wm_read_history(void);
int wm_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports);
int wm_history_read_exec(bContext *C, wmOperator *op);
int wm_homefile_read_exec(struct bContext *C, struct wmOperator *op);
-int wm_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory);
+int wm_homefile_read(struct bContext *C, struct ReportList *reports, bool from_memory, const char *filepath);
int wm_homefile_write_exec(struct bContext *C, struct wmOperator *op);
int wm_userpref_write_exec(struct 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 f61b54ac360..7ff5f83c21c 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -173,6 +173,7 @@ void modifier_skin_customdata_ensure(struct Object *ob) {STUB_ASSERT(0);}
/* nodes */
struct RenderResult *RE_GetResult(struct Render *re) {STUB_ASSERT(0); return (struct RenderResult *) NULL;}
struct Render *RE_GetRender(const char *name) {STUB_ASSERT(0); return (struct Render *) NULL;}
+float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[3], float lv[3], float *dist) {STUB_ASSERT(0); return 0.0f;}
/* blenkernel */
void RE_FreeRenderResult(struct RenderResult *res) {STUB_ASSERT(0);}
@@ -468,8 +469,8 @@ void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int ex
void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {STUB_ASSERT(0);}
void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {STUB_ASSERT(0);}
void uiTemplateList(struct uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
- PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type, int columns) {STUB_ASSERT(0);}
+ PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname,
+ int rows, int maxrows, int layout_type, int columns) {STUB_ASSERT(0);}
void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}
void uiTemplateOperatorSearch(struct uiLayout *layout) {STUB_ASSERT(0);}
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index cb745d46fa4..2a355bd5606 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -932,7 +932,6 @@ endif()
bf_editor_io
bf_render
- bf_intern_opennl
bf_python
bf_python_ext
bf_python_mathutils
@@ -1061,6 +1060,10 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
endif()
+ if(WITH_OPENNL)
+ list_insert_after(BLENDER_SORTED_LIBS "bf_render" "bf_intern_opennl")
+ endif()
+
if(WITH_BULLET)
list_insert_after(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_intern_rigidbody")
endif()
diff --git a/source/creator/creator.c b/source/creator/creator.c
index adedab80338..9889eacc5db 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -63,6 +63,7 @@
#include <stddef.h>
#include <string.h>
#include <errno.h>
+#include <time.h>
/* This little block needed for linking to Blender... */
@@ -1273,6 +1274,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
DAG_on_visible_update(CTX_data_main(C), TRUE);
+ BKE_scene_update_tagged(CTX_data_main(C), CTX_data_scene(C));
}
else {
/* failed to load file, stop processing arguments */
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 1b27fde4fa4..eeaffd9005a 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1513,6 +1513,7 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
objprop.m_character = (blenderobject->gameflag & OB_CHARACTER) != 0;
+ objprop.m_record_animation = (blenderobject->gameflag & OB_RECORD_ANIMATION) != 0;
///contact processing threshold is only for rigid bodies and static geometry, not 'dynamic'
if (objprop.m_angular_rigidbody || !objprop.m_dyna )
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index e682f335608..4ed8e3e8a03 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -706,8 +706,7 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
for (g=0;g<numObjects;g++)
{
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
- if (gameObj->IsDynamic())
- {
+ if (gameObj->IsRecordAnimation()) {
Object* blenderObject = gameObj->GetBlenderObject();
if (blenderObject)
@@ -769,7 +768,7 @@ void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
CListValue* parentList = scene->GetRootParentList();
for (int ix=0;ix<parentList->GetCount();ix++) {
KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
- if (!gameobj->IsDynamic()) {
+ if (!gameobj->IsRecordAnimation()) {
Object* blenderobject = gameobj->GetBlenderObject();
if (!blenderobject)
continue;
@@ -821,8 +820,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
{
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->parent==NULL && gameObj->IsDynamic())
- {
+ if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) {
if (blenderObject->adt==NULL)
BKE_id_add_animdata(&blenderObject->id);
@@ -939,9 +937,7 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
for (g=0;g<numObjects;g++)
{
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
- if (gameObj->IsDynamic())
- {
-
+ if (gameObj->IsRecordAnimation()) {
#if 0
Object* blenderObject = gameObj->GetBlenderObject();
if (blenderObject && blenderObject->ipo)
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index e9461a15578..26401fcd868 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -80,7 +80,7 @@
/* This little block needed for linking to Blender... */
#include "BKE_text.h"
#include "BLI_blenlib.h"
-#include "BLI_math_base.h"
+#include "BLI_math.h"
#include "BLI_path_util.h"
#include "KX_NetworkMessageActuator.h"
@@ -386,8 +386,8 @@ void BL_ConvertActuators(const char* maggiename,
bool is3d = soundact->flag & ACT_SND_3D_SOUND ? true : false;
boost::shared_ptr<AUD_IFactory> snd_sound;
KX_3DSoundSettings settings;
- settings.cone_inner_angle = soundact->sound3D.cone_inner_angle;
- settings.cone_outer_angle = soundact->sound3D.cone_outer_angle;
+ settings.cone_inner_angle = RAD2DEGF(soundact->sound3D.cone_inner_angle);
+ settings.cone_outer_angle = RAD2DEGF(soundact->sound3D.cone_outer_angle);
settings.cone_outer_gain = soundact->sound3D.cone_outer_gain;
settings.max_distance = soundact->sound3D.max_distance;
settings.max_gain = soundact->sound3D.max_gain;
@@ -571,8 +571,8 @@ void BL_ConvertActuators(const char* maggiename,
/* convert settings... degrees in the ui become radians */
/* internally */
if (conact->type == ACT_CONST_TYPE_ORI) {
- min = (float)(((float)MT_2_PI * conact->minloc[0]) / 360.0f);
- max = (float)(((float)MT_2_PI * conact->maxloc[0]) / 360.0f);
+ min = conact->minloc[0];
+ max = conact->maxloc[0];
switch (conact->mode) {
case ACT_CONST_DIRPX:
locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX;
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index b9bd9aabc54..860dd5c06fb 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -431,7 +431,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
// or the blenderradarsensor->angle?
// nzc: the angle is the opening angle. We need to init with
// the axis-hull angle,so /2.0.
- MT_Scalar factor = tan(MT_radians((blenderradarsensor->angle) / 2.0f));
+ MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f);
//MT_Scalar coneradius = coneheight * (factor / 2);
MT_Scalar coneradius = coneheight * factor;
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 793ce6a7b83..6e379c91d0c 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -293,10 +293,11 @@ void SCA_Joystick::DestroyJoystickDevice(void)
#ifdef WITH_SDL
if (m_isinit) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
- if (SDL_JoystickGetAttached(m_private->m_joystick)) {
+ if (SDL_JoystickGetAttached(m_private->m_joystick))
#else
- if (SDL_JoystickOpened(m_joyindex)) {
+ if (SDL_JoystickOpened(m_joyindex))
#endif
+ {
JOYSTICK_ECHO("Closing-joystick " << m_joyindex);
SDL_JoystickClose(m_private->m_joystick);
}
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index f02ac495233..ad57e529297 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -207,6 +207,7 @@ bool SCA_PropertySensor::CheckPropertyCondition()
result = (min <= val) && (val <= max);
}
+ orgprop->Release();
break;
}
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index 903966b79be..1ed3a998b99 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -71,6 +71,7 @@ struct KX_ObjectProperties
bool m_ghost;
class KX_GameObject* m_dynamic_parent;
bool m_isactor;
+ bool m_record_animation;
bool m_sensor;
bool m_character;
bool m_concave;
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index bde50588fd3..16513a97d60 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -435,6 +435,11 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
shapeInfo->Release();
gameobj->SetPhysicsController(physicscontroller,isbulletdyna);
+
+ // record animation for dynamic objects
+ if (isbulletdyna)
+ gameobj->SetRecordAnimation(true);
+
// don't add automatically sensor object, they are added when a collision sensor is registered
if (!isbulletsensor && objprop->m_in_active_layer)
{
@@ -493,6 +498,11 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
gameobj->getClientInfo()->m_type =
(isbulletsensor) ? ((isActor) ? KX_ClientObjectInfo::OBACTORSENSOR : KX_ClientObjectInfo::OBSENSOR) :
(isActor) ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC;
+
+ // should we record animation for this object?
+ if (objprop->m_record_animation)
+ gameobj->SetRecordAnimation(true);
+
// store materialname in auxinfo, needed for touchsensors
if (meshobj)
{
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 96f76ff21b1..d3b5a987138 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -112,6 +112,7 @@ KX_GameObject::KX_GameObject(
m_pInstanceObjects(NULL),
m_pDupliGroupObject(NULL),
m_actionManager(NULL),
+ m_bRecordAnimation(false),
m_isDeformable(false)
#ifdef WITH_PYTHON
@@ -1791,6 +1792,7 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible),
+ KX_PYATTRIBUTE_RW_FUNCTION("record_animation", KX_GameObject, pyattr_get_record_animation, pyattr_set_record_animation),
KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder),
KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_worldPosition, pyattr_set_localPosition),
KX_PYATTRIBUTE_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia),
@@ -2258,6 +2260,28 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyBool_FromLong(self->IsRecordAnimation());
+}
+
+int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ int param = PyObject_IsTrue(value);
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "gameOb.record_animation = bool: KX_GameObject, expected boolean");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->SetRecordAnimation(param);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+
+
PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
#ifdef USE_MATHUTILS
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 55e2b31c5bf..12aac68365b 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -126,6 +126,7 @@ protected:
BL_ActionManager* GetActionManager();
+ bool m_bRecordAnimation;
public:
bool m_isDeformable;
@@ -600,6 +601,20 @@ public:
}
/**
+ * Should we record animation for this object?
+ */
+
+ void SetRecordAnimation(bool recordAnimation)
+ {
+ m_bRecordAnimation = recordAnimation;
+ }
+
+ bool IsRecordAnimation() const
+ {
+ return m_bRecordAnimation;
+ }
+
+ /**
* Check if this object has a vertex parent relationship
*/
bool IsVertexParent( )
@@ -981,6 +996,8 @@ public:
static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 4567c17cc3e..3a8821e8a86 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -51,7 +51,9 @@
#include "BKE_scene.h"
#include "MEM_guardedalloc.h"
-
+
+#include "BLI_math.h"
+
KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
RAS_IRasterizer* rasterizer,
const RAS_LightObject& lightobj,
@@ -158,7 +160,7 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot)
//vec[1] = -base->object->obmat[2][1];
//vec[2] = -base->object->obmat[2][2];
glLightfv((GLenum)(GL_LIGHT0+slot), GL_SPOT_DIRECTION, vec);
- glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_CUTOFF, m_lightobj.m_spotsize / 2.0f);
+ glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_CUTOFF, RAD2DEGF(m_lightobj.m_spotsize * 0.5f));
glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_EXPONENT, 128.0f * m_lightobj.m_spotblend);
}
else {
@@ -360,7 +362,7 @@ PyAttributeDef KX_LightObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color),
KX_PYATTRIBUTE_FLOAT_RW("lin_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att1),
KX_PYATTRIBUTE_FLOAT_RW("quad_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att2),
- KX_PYATTRIBUTE_FLOAT_RW("spotsize", 1, 180, KX_LightObject, m_lightobj.m_spotsize),
+ KX_PYATTRIBUTE_RW_FUNCTION("spotsize", KX_LightObject, pyattr_get_spotsize, pyattr_set_spotsize),
KX_PYATTRIBUTE_FLOAT_RW("spotblend", 0, 1, KX_LightObject, m_lightobj.m_spotblend),
KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst),
KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst),
@@ -390,6 +392,28 @@ int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *att
return PY_SET_ATTR_FAIL;
}
+PyObject *KX_LightObject::pyattr_get_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+ return Py_BuildValue("f", RAD2DEGF(self->m_lightobj.m_spotsize));
+}
+
+int KX_LightObject::pyattr_set_spotsize(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_LightObject* self = static_cast<KX_LightObject*>(self_v);
+
+ float spotsize = (float)PyFloat_AsDouble(value);
+ if (PyErr_Occurred())
+ return PY_SET_ATTR_FAIL;
+
+ if (spotsize < 1.0f)
+ spotsize = 1.0f;
+ else if (spotsize > 180.0f)
+ spotsize = 180.0f;
+ self->m_lightobj.m_spotsize = DEG2RADF(spotsize);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
PyObject *retvalue;
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 4f11c535cf0..d6892875042 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -78,6 +78,8 @@ public:
/* attributes */
static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_spotsize(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_spotsize(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_typeconst(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 2f23bdaccb7..70924c65519 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -2398,7 +2398,6 @@ PyAttributeDef KX_Scene::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive),
KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights),
KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras),
- KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights),
KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre),
KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post),
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 3a4b1d82946..4e5cd0ac5e1 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -147,7 +147,7 @@ CValue* KX_SoundActuator::GetReplica()
KX_SoundActuator* replica = new KX_SoundActuator(*this);
replica->ProcessReplica();
return replica;
-};
+}
void KX_SoundActuator::ProcessReplica()
{
@@ -217,11 +217,12 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
// m_posevent==false && m_posevent==false, in this case IsNegativeEvent() returns false
// and assumes this is a positive event.
// check that we actually have a positive event so as not to play sounds when being disabled.
- else if (bPositiveEvent) { // <- added since 2.49
+ else if (bPositiveEvent) /* <- added since 2.49 */
#else
- else { // <- works in most cases except a loop-end sound will never stop unless
+ else // <- works in most cases except a loop-end sound will never stop unless
// the negative pulse is done continuesly
#endif
+ {
if (!m_isplaying)
play();
}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 6ce52b60426..6be6400e011 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -145,6 +145,8 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
m_bulletMotionState = 0;
m_characterController = 0;
m_savedCollisionFlags = 0;
+ m_savedCollisionFilterGroup = 0;
+ m_savedCollisionFilterMask = 0;
m_savedMass = 0.0;
m_suspended = false;
@@ -1057,8 +1059,12 @@ void CcdPhysicsController::SuspendDynamics(bool ghost)
btRigidBody *body = GetRigidBody();
if (body && !m_suspended && !GetConstructionInfo().m_bSensor)
{
+ btBroadphaseProxy* handle = body->getBroadphaseHandle();
+
m_savedCollisionFlags = body->getCollisionFlags();
m_savedMass = GetMass();
+ m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
+ m_savedCollisionFilterMask = handle->m_collisionFilterMask;
m_suspended = true;
GetPhysicsEnvironment()->UpdateCcdPhysicsController(this,
0.0,
@@ -1078,8 +1084,8 @@ void CcdPhysicsController::RestoreDynamics()
GetPhysicsEnvironment()->UpdateCcdPhysicsController(this,
m_savedMass,
m_savedCollisionFlags,
- GetConstructionInfo().m_collisionFilterGroup,
- GetConstructionInfo().m_collisionFilterMask);
+ m_savedCollisionFilterGroup,
+ m_savedCollisionFilterMask);
body->activate();
m_suspended = false;
}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 194a47ae2df..0d6d40861c5 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -478,9 +478,12 @@ protected:
CcdPhysicsController* m_parentCtrl;
int m_savedCollisionFlags;
+ short m_savedCollisionFilterGroup;
+ short m_savedCollisionFilterMask;
MT_Scalar m_savedMass;
bool m_suspended;
+
void GetWorldOrientation(btMatrix3x3& mat);
void CreateRigidbody();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 5105e2c2b8d..2884983a17e 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -1229,7 +1229,7 @@ void RAS_OpenGLRasterizer::RemoveLight(struct RAS_LightObject* lightobject)
m_lights.erase(lit);
}
-bool RAS_OpenGLRasterizer::RayHit(class KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
+bool RAS_OpenGLRasterizer::RayHit(struct KX_ClientObjectInfo *client, KX_RayCast *result, void * const data)
{
double* const oglmatrix = (double* const) data;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index e1159ab3d2d..01c42050b36 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -380,8 +380,8 @@ public:
void PushMatrix();
void PopMatrix();
- bool RayHit(class KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data);
- bool NeedRayCast(class KX_ClientObjectInfo*) { return true; }
+ bool RayHit(struct KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data);
+ bool NeedRayCast(struct KX_ClientObjectInfo*) { return true; }
void AddLight(struct RAS_LightObject* lightobject);
diff --git a/source/tests/bl_rna_wiki_reference.py b/source/tests/bl_rna_wiki_reference.py
index cfe7f22f7dd..c394107d8d1 100644
--- a/source/tests/bl_rna_wiki_reference.py
+++ b/source/tests/bl_rna_wiki_reference.py
@@ -87,18 +87,58 @@ def test_lookup_coverage():
print("%s.*" % rna_group)
-def test_urls():
+def test_language_coverage():
pass # TODO
-def test_language_coverage():
- pass # TODO
+def test_urls():
+ import sys
+ import rna_wiki_reference
+
+ import urllib.error
+ from urllib.request import urlopen
+
+ prefix = rna_wiki_reference.url_manual_prefix
+ urls = {suffix for (rna_id, suffix) in rna_wiki_reference.url_manual_mapping}
+
+ urls_len = "%d" % len(urls)
+ print("")
+ print("-------------" + "-" * len(urls_len))
+ print("Testing URLS %s" % urls_len)
+ print("")
+
+ color_red = '\033[0;31m'
+ color_green = '\033[1;32m'
+ color_normal = '\033[0m'
+
+ urls_fail = []
+
+ for url in sorted(urls):
+ url_full = prefix + url
+ print(" %s ... " % url_full, end="")
+ sys.stdout.flush()
+ try:
+ urllib.request.urlopen(url_full)
+ print(color_green + "OK" + color_normal)
+ except urllib.error.HTTPError:
+ print(color_red + "FAIL!" + color_normal)
+ urls_fail.append(url)
+
+ if urls_fail:
+ urls_len = "%d" % len(urls_fail)
+ print("")
+ print("------------" + "-" * len(urls_len))
+ print("Failed URLS %s" % urls_len)
+ print("")
+ for url in urls_fail:
+ print(" %s%s%s" % (color_red, url, color_normal))
def main():
test_data()
test_lookup_coverage()
test_language_coverage()
+ test_urls()
if __name__ == "__main__":
main()